Skip to content

Commit 32d5ecd

Browse files
authored
Merge pull request #12 from VelkoTgr6/development
Update
2 parents 7ad2435 + 48442aa commit 32d5ecd

24 files changed

+982
-233
lines changed

StudentManagementSystem.Core/Models/Teacher/AbsenceFormViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ public class AbsenceFormViewModel
88
public string CourseName { get; set; } = string.Empty;
99
public int CourseId { get; set; }
1010
public IEnumerable<TeacherCourseServiceModel> Courses { get; set; } = new List<TeacherCourseServiceModel>();
11-
public DateTime AbsenceDate { get; set; } = DateTime.Now;
11+
public DateTime AbsenceDate { get; set; } = DateTime.UtcNow;
1212
}
1313
}

StudentManagementSystem.Core/Services/Admin/AdminClassService.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.Extensions.Logging;
23
using StudentManagementSystem.Core.Contracts.Admin;
34
using StudentManagementSystem.Core.Enumerations;
45
using StudentManagementSystem.Core.Models.Admin.Class;
@@ -11,10 +12,12 @@ namespace StudentManagementSystem.Core.Services.Admin
1112
public class AdminClassService : IAdminClassService
1213
{
1314
private readonly IRepository repository;
15+
private readonly ILogger<AdminClassService> logger;
1416

15-
public AdminClassService(IRepository _repository)
17+
public AdminClassService(IRepository _repository, ILogger<AdminClassService> _logger)
1618
{
1719
repository = _repository;
20+
logger = _logger;
1821
}
1922

2023
public async Task<ClassQueryServiceModel> AllAsync(string? teacher = null, string? searchTerm = null, ClassSorting sorting = ClassSorting.Name, int currentPage = 1, int classesPerPage = 10)
@@ -76,6 +79,15 @@ public Task<bool> ClassExistAsync(int id)
7679

7780
public async Task<int> CreateClassAsync(ClassFormViewModel model)
7881
{
82+
var exists = await repository.AllAsReadOnly<Class>()
83+
.AnyAsync(c => c.Name.ToLower() == model.Name.ToLower() && c.IsDeleted == false);
84+
85+
if (exists)
86+
{
87+
logger.LogWarning($"Attempt to create duplicate class with name: {model.Name}");
88+
throw new InvalidOperationException($"Class with the same name {model.Name} already exists.");
89+
}
90+
7991
var entity = new Class
8092
{
8193
Name = model.Name,
@@ -92,6 +104,8 @@ public async Task<int> CreateClassAsync(ClassFormViewModel model)
92104
await repository.AddAsync(entity);
93105
await repository.SaveChangesAsync();
94106

107+
logger.LogInformation($"Class created with ID: {entity.Id} and Name: {entity.Name}");
108+
95109
return entity.Id;
96110
}
97111

@@ -103,8 +117,15 @@ public async Task DeleteClassAsync(int id)
103117
{
104118
selectedClass.IsDeleted = true;
105119
}
120+
else
121+
{
122+
logger.LogWarning($"Attempt to delete non-existing or already deleted class with ID: {id}");
123+
throw new KeyNotFoundException($"Class with ID {id} not found or already deleted.");
124+
}
106125

107126
await repository.SaveChangesAsync();
127+
128+
logger.LogInformation($"Class with ID: {id} has been marked as deleted.");
108129
}
109130

110131
public async Task EditClassAsync(int id, ClassFormViewModel model)
@@ -143,11 +164,17 @@ public async Task EditClassAsync(int id, ClassFormViewModel model)
143164
if (courseToRemove != null)
144165
{
145166
entity.ClassCourses.Remove(courseToRemove);
167+
logger.LogInformation($"Removed course with ID: {courseId} from class ID: {id}");
146168
}
147169
}
148170

149171
await repository.SaveChangesAsync();
150172
}
173+
else
174+
{
175+
logger.LogWarning($"Attempt to edit non-existing or deleted class with ID: {id}");
176+
throw new KeyNotFoundException($"Class with ID {id} not found.");
177+
}
151178
}
152179

153180

@@ -162,6 +189,11 @@ public async Task<IEnumerable<ClassServiceModel>> GetAllClassesAsync()
162189
})
163190
.ToListAsync();
164191

192+
if (!classes.Any())
193+
{
194+
throw new InvalidOperationException("No classes found.");
195+
}
196+
165197
classes = SortClassNames(classes.Select(c => c.Name))
166198
.Select(name => classes.First(c => c.Name == name))
167199
.ToList();
@@ -177,6 +209,11 @@ public async Task<IEnumerable<string>> GetAllClassesNamesAsync()
177209
.Select(c => c.Name)
178210
.ToListAsync();
179211

212+
if (!classes.Any())
213+
{
214+
throw new InvalidOperationException("No classes found.");
215+
}
216+
180217
classes = SortClassNames(classes).ToList();
181218

182219
return classes;
@@ -205,7 +242,7 @@ public async Task<ClassDetailsViewModel> GetClassDetailsModelByIdAsync(int id)
205242

206243
if (classDetails == null)
207244
{
208-
throw new InvalidOperationException("Class not found.");
245+
throw new KeyNotFoundException($"Class with ID {id} not found.");
209246
}
210247

211248
return classDetails;

StudentManagementSystem.Core/Services/Admin/AdminCourseService.cs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.Extensions.Logging;
23
using StudentManagementSystem.Core.Contracts.Admin;
34
using StudentManagementSystem.Core.Enumerations;
45
using StudentManagementSystem.Core.Models.Admin.Course;
@@ -10,18 +11,19 @@ namespace StudentManagementSystem.Core.Services.Admin
1011
public class AdminCourseService : IAdminCourseService
1112
{
1213
private readonly IRepository repository;
14+
private readonly ILogger<AdminCourseService> logger;
1315

14-
public AdminCourseService(IRepository _repository)
16+
public AdminCourseService(IRepository _repository, ILogger<AdminCourseService> _logger)
1517
{
1618
repository = _repository;
19+
logger = _logger;
1720
}
1821

1922
public async Task<CourseQueryServiceModel> AllAsync(string? teacher = null, string? searchTerm = null, CourseSorting sorting = CourseSorting.Name, int currentPage = 1, int coursesPerPage = 10)
2023
{
2124
var courseQuery = repository.AllAsReadOnly<Course>().Where(s => s.IsDeleted == false);
2225

2326

24-
2527
if (!string.IsNullOrWhiteSpace(teacher))
2628
{
2729
string[] teacherNameArr = teacher.Split(' ', StringSplitOptions.RemoveEmptyEntries);
@@ -70,13 +72,29 @@ public async Task<CourseQueryServiceModel> AllAsync(string? teacher = null, stri
7072

7173
public async Task<bool> CourseExistAsync(int id)
7274
{
73-
return await repository.AllAsReadOnly<Course>()
75+
var courseExists = await repository.AllAsReadOnly<Course>()
7476
.Where(c => c.IsDeleted == false)
7577
.AnyAsync(c => c.Id == id);
78+
79+
if (!courseExists)
80+
{
81+
throw new KeyNotFoundException($"Course with ID: {id} not found");
82+
}
83+
84+
return courseExists;
7685
}
7786

7887
public async Task<int> CreateCourseAsync(CourseFormViewModel model, string publisherId)
7988
{
89+
var existingCourse = await repository.AllAsReadOnly<Course>()
90+
.FirstOrDefaultAsync(c => c.Name.ToLower() == model.Name.ToLower() && c.IsDeleted == false);
91+
92+
if (existingCourse != null)
93+
{
94+
logger.LogWarning($"Attempted to create a course with an existing name: {model.Name}");
95+
throw new InvalidOperationException($"Course with name '{model.Name}' already exists.");
96+
}
97+
8098
var entity = new Course
8199
{
82100
Name = model.Name,
@@ -88,6 +106,8 @@ public async Task<int> CreateCourseAsync(CourseFormViewModel model, string publi
88106
await repository.AddAsync(entity);
89107
await repository.SaveChangesAsync();
90108

109+
logger.LogInformation($"Created new course with ID: {entity.Id} and Name: {entity.Name}");
110+
91111
return entity.Id;
92112
}
93113

@@ -99,8 +119,15 @@ public async Task DeleteCourseAsync(int id)
99119
{
100120
course.IsDeleted = true;
101121
}
122+
else
123+
{
124+
logger.LogWarning($"Attempted to delete a non-existing or already deleted course with ID: {id}");
125+
throw new KeyNotFoundException($"Course with ID {id} not found.");
126+
}
102127

103128
await repository.SaveChangesAsync();
129+
130+
logger.LogInformation($"Deleted course with ID: {id} and Name: {course.Name}");
104131
}
105132

106133
public async Task EditCourseAsync(int id, CourseFormViewModel model, string publisherId)
@@ -114,29 +141,50 @@ public async Task EditCourseAsync(int id, CourseFormViewModel model, string publ
114141
course.TeacherId = model.TeacherId;
115142
course.PublisherId = publisherId;
116143
}
144+
else
145+
{
146+
logger.LogWarning($"Attempted to edit a non-existing or deleted course with ID: {id}");
147+
throw new KeyNotFoundException($"Course with ID {id} not found.");
148+
}
117149

118150
await repository.SaveChangesAsync();
151+
152+
logger.LogInformation($"Edited course with ID: {id} and new Name: {course.Name}");
119153
}
120154

121155
public async Task<IEnumerable<CourseServiceModel>> GetAllCoursesAsync()
122156
{
123-
return await repository.AllAsReadOnly<Course>()
124-
.Where(c => c.IsDeleted == false)
157+
var courses = await repository.AllAsReadOnly<Course>()
158+
.Where(c => c.IsDeleted == false)
125159
.Select(c => new CourseServiceModel
126160
{
127161
Id = c.Id,
128162
Name = c.Name
129163
})
130164
.ToListAsync();
165+
166+
if (!courses.Any())
167+
{
168+
throw new InvalidOperationException("No courses available.");
169+
}
170+
171+
return courses;
131172
}
132173

133174
public async Task<IEnumerable<string>> GetAllCoursesNamesAsync()
134175
{
135-
return await repository.AllAsReadOnly<Course>()
176+
var coursesNames = await repository.AllAsReadOnly<Course>()
136177
.Where(c => c.IsDeleted == false)
137178
.OrderBy(c => c.Name)
138179
.Select(c => c.Name)
139180
.ToListAsync();
181+
182+
if (!coursesNames.Any())
183+
{
184+
throw new InvalidOperationException("No course names available.");
185+
}
186+
187+
return coursesNames;
140188
}
141189

142190
public async Task<CourseServiceModel> GetCourseByIdAsync(int id)
@@ -145,7 +193,7 @@ public async Task<CourseServiceModel> GetCourseByIdAsync(int id)
145193

146194
if (course == null)
147195
{
148-
throw new ArgumentException($"Course with ID {id} not found.");
196+
throw new KeyNotFoundException($"Course with ID {id} not found.");
149197
}
150198

151199
return course;
@@ -166,7 +214,7 @@ public async Task<CourseDetailsViewModel> GetCourseDetailsModelByIdAsync(int id)
166214

167215
if (course == null)
168216
{
169-
throw new ArgumentException($"Course with ID {id} not found.");
217+
throw new KeyNotFoundException($"Course with ID {id} not found.");
170218
}
171219

172220
return course;
@@ -186,7 +234,7 @@ public async Task<CourseFormViewModel> GetCourseFormModelByIdAsync(int id)
186234

187235
if (course == null)
188236
{
189-
throw new ArgumentException($"Course with ID {id} not found.");
237+
throw new KeyNotFoundException($"Course with ID {id} not found.");
190238
}
191239

192240
return course;

StudentManagementSystem.Core/Services/Admin/AdminScheduleService.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.Extensions.Logging;
23
using StudentManagementSystem.Core.Contracts.Admin;
34
using StudentManagementSystem.Core.Models.Admin.Schedule;
45
using StudentManagementSystem.Infrastructure.Data.Common;
@@ -9,10 +10,12 @@ namespace StudentManagementSystem.Core.Services.Admin
910
public class AdminScheduleService : IAdminScheduleService
1011
{
1112
private readonly IRepository repository;
13+
private readonly ILogger<AdminScheduleService> logger;
1214

13-
public AdminScheduleService(IRepository _repository)
15+
public AdminScheduleService(IRepository _repository, ILogger<AdminScheduleService> _logger)
1416
{
1517
repository = _repository;
18+
logger = _logger;
1619
}
1720

1821
public async Task<IEnumerable<CourseScheduleViewModel>> GetCourseSchedulesByIdAsync(int id)
@@ -35,6 +38,20 @@ public async Task<IEnumerable<CourseScheduleViewModel>> GetCourseSchedulesByIdAs
3538

3639
public async Task AddCourseScheduleAsync(CourseScheduleInputModel model)
3740
{
41+
var existingSchedule = await repository.AllAsReadOnly<CourseSchedule>()
42+
.FirstOrDefaultAsync(cs =>
43+
cs.ClassId == model.ClassId &&
44+
cs.Day == model.Day &&
45+
((model.StartTime >= cs.StartTime && model.StartTime < cs.EndTime) ||
46+
(model.EndTime > cs.StartTime && model.EndTime <= cs.EndTime) ||
47+
(model.StartTime <= cs.StartTime && model.EndTime >= cs.EndTime)));
48+
49+
if (existingSchedule != null)
50+
{
51+
logger.LogError("Schedule conflict detected when trying to add a new course schedule.");
52+
throw new InvalidOperationException("The class already has a schedule that conflicts with the specified time.");
53+
}
54+
3855
var courseSchedule = new CourseSchedule
3956
{
4057
CourseId = model.CourseId,
@@ -45,17 +62,26 @@ public async Task AddCourseScheduleAsync(CourseScheduleInputModel model)
4562
};
4663

4764
await repository.AddAsync(courseSchedule);
65+
66+
logger.LogInformation($"Added new course schedule: {courseSchedule.Id}");
67+
4868
await repository.SaveChangesAsync();
4969
}
5070

5171
public async Task DeleteCourseScheduleAsync(int id)
5272
{
5373
var courseSchedule = await repository.GetByIdAsync<CourseSchedule>(id);
74+
5475
if (courseSchedule != null)
5576
{
5677
repository.DeleteSchedule(courseSchedule);
5778
await repository.SaveChangesAsync();
5879
}
80+
else
81+
{
82+
logger.LogWarning($"Attempted to delete a non-existing or already deleted course schedule with ID: {id}.");
83+
throw new KeyNotFoundException($"Course schedule with ID: {id} not found.");
84+
}
5985
}
6086

6187
public async Task EditCourseScheduleAsync(int id, CourseScheduleInputModel model)
@@ -73,6 +99,11 @@ public async Task EditCourseScheduleAsync(int id, CourseScheduleInputModel model
7399
schedule.EndTime = model.EndTime;
74100
await repository.SaveChangesAsync();
75101
}
102+
else
103+
{
104+
logger.LogWarning($"Attempted to edit a non-existing course schedule with ID: {id}.");
105+
throw new KeyNotFoundException($"Course schedule with ID: {id} not found.");
106+
}
76107
}
77108

78109
public async Task<CourseScheduleInputModel> GetCourseScheduleByIdAsync(int id)
@@ -94,7 +125,7 @@ public async Task<CourseScheduleInputModel> GetCourseScheduleByIdAsync(int id)
94125

95126
if (courseSchedule == null)
96127
{
97-
throw new Exception("Course schedule not found");
128+
throw new KeyNotFoundException($"Course schedule with ID: {id} not found.");
98129
}
99130

100131
return courseSchedule;

0 commit comments

Comments
 (0)