diff --git a/ApiDto/ApiDto.csproj b/ApiDto/ApiDto.csproj new file mode 100644 index 0000000..f806393 --- /dev/null +++ b/ApiDto/ApiDto.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + disable + enable + Winsomnia + 1.0.0-a0 + 1.0.0.0 + 1.0.0.0 + Mirea.Api.Dto + $(AssemblyName) + True + ApiDtoDocs.xml + + + + + Always + + + + diff --git a/ApiDto/Requests/ScheduleRequest.cs b/ApiDto/Requests/ScheduleRequest.cs new file mode 100644 index 0000000..476d8f3 --- /dev/null +++ b/ApiDto/Requests/ScheduleRequest.cs @@ -0,0 +1,37 @@ +namespace Mirea.Api.Dto.Requests; + +/// +/// Represents a request object for retrieving schedules based on various filters. +/// +public class ScheduleRequest +{ + /// + /// Gets or sets an array of group IDs. + /// + /// This array can contain null values. + public int[]? Groups { get; set; } = null; + + /// + /// Gets or sets a value indicating whether to retrieve schedules for even weeks. + /// + /// This property can contain null. + public bool? IsEven { get; set; } = null; + + /// + /// Gets or sets an array of discipline IDs. + /// + /// This array can contain null values. + public int[]? Disciplines { get; set; } = null; + + /// + /// Gets or sets an array of professor IDs. + /// + /// This array can contain null values. + public int[]? Professors { get; set; } = null; + + /// + /// Gets or sets an array of lecture hall IDs. + /// + /// This array can contain null values. + public int[]? LectureHalls { get; set; } = null; +} diff --git a/ApiDto/Responses/CampusBasicInfoResponse.cs b/ApiDto/Responses/CampusBasicInfoResponse.cs new file mode 100644 index 0000000..4ad46a7 --- /dev/null +++ b/ApiDto/Responses/CampusBasicInfoResponse.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents basic information about a campus. +/// +public class CampusBasicInfoResponse +{ + /// + /// Gets or sets the unique identifier of the campus. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the code name of the campus. + /// + [Required] + public required string CodeName { get; set; } + + /// + /// Gets or sets the full name of the campus (optional). + /// + public string? FullName { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/CampusDetailsResponse.cs b/ApiDto/Responses/CampusDetailsResponse.cs new file mode 100644 index 0000000..82db94e --- /dev/null +++ b/ApiDto/Responses/CampusDetailsResponse.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents detailed information about a campus. +/// +public class CampusDetailsResponse +{ + /// + /// Gets or sets the unique identifier of the campus. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the code name of the campus. + /// + [Required] + public required string CodeName { get; set; } + + /// + /// Gets or sets the full name of the campus (optional). + /// + public string? FullName { get; set; } + + /// + /// Gets or sets the address of the campus (optional). + /// + public string? Address { get; set; } +} diff --git a/ApiDto/Responses/DisciplineResponse.cs b/ApiDto/Responses/DisciplineResponse.cs new file mode 100644 index 0000000..9b35e13 --- /dev/null +++ b/ApiDto/Responses/DisciplineResponse.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents information about a discipline. +/// +public class DisciplineResponse +{ + /// + /// Gets or sets the unique identifier of the discipline. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the discipline. + /// + [Required] + public required string Name { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/ErrorResponse.cs b/ApiDto/Responses/ErrorResponse.cs new file mode 100644 index 0000000..f0dc33c --- /dev/null +++ b/ApiDto/Responses/ErrorResponse.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// A class for providing information about an error +/// +public class ErrorResponse +{ + /// + /// The text or translation code of the error. This field may not contain information in specific scenarios. + /// For example, it might be empty for HTTP 204 responses where no content is returned or if the validation texts have not been configured. + /// + [Required] + public required string Error { get; set; } + /// + /// In addition to returning the response code in the header, it is also duplicated in this field. + /// Represents the HTTP response code. + /// + [Required] + public required int Code { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/FacultyDetailsResponse.cs b/ApiDto/Responses/FacultyDetailsResponse.cs new file mode 100644 index 0000000..09c863b --- /dev/null +++ b/ApiDto/Responses/FacultyDetailsResponse.cs @@ -0,0 +1,36 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents detailed information about a faculty. +/// +public class FacultyDetailsResponse +{ + /// + /// Gets or sets the unique identifier of the faculty. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the faculty. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the unique identifier of the campus to which the faculty belongs (optional). + /// + public int? CampusId { get; set; } + + /// + /// Gets or sets the name of the campus to which the faculty belongs (optional). + /// + public string? CampusName { get; set; } + + /// + /// Gets or sets the code name of the campus to which the faculty belongs (optional). + /// + public string? CampusCode { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/FacultyResponse.cs b/ApiDto/Responses/FacultyResponse.cs new file mode 100644 index 0000000..adcf127 --- /dev/null +++ b/ApiDto/Responses/FacultyResponse.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents basic information about a faculty. +/// +public class FacultyResponse +{ + /// + /// Gets or sets the unique identifier of the faculty. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the faculty. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the unique identifier of the campus to which the faculty belongs (optional). + /// + public int? CampusId { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/GroupDetailsResponse.cs b/ApiDto/Responses/GroupDetailsResponse.cs new file mode 100644 index 0000000..44670fe --- /dev/null +++ b/ApiDto/Responses/GroupDetailsResponse.cs @@ -0,0 +1,37 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents detailed information about a group. +/// +public class GroupDetailsResponse +{ + /// + /// Gets or sets the unique identifier of the group. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the group. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the course number of the group. + /// + [Required] + public int CourseNumber { get; set; } + + /// + /// Gets or sets the unique identifier of the faculty to which the group belongs (optional). + /// + public int? FacultyId { get; set; } + + /// + /// Gets or sets the name of the faculty to which the group belongs (optional). + /// + public string? FacultyName { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/GroupResponse.cs b/ApiDto/Responses/GroupResponse.cs new file mode 100644 index 0000000..0177459 --- /dev/null +++ b/ApiDto/Responses/GroupResponse.cs @@ -0,0 +1,32 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents basic information about a group. +/// +public class GroupResponse +{ + /// + /// Gets or sets the unique identifier of the group. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the group. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the course number of the group. + /// + [Required] + public int CourseNumber { get; set; } + + /// + /// Gets or sets the unique identifier of the faculty to which the group belongs (optional). + /// + public int? FacultyId { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/LectureHallDetailsResponse.cs b/ApiDto/Responses/LectureHallDetailsResponse.cs new file mode 100644 index 0000000..67b1a66 --- /dev/null +++ b/ApiDto/Responses/LectureHallDetailsResponse.cs @@ -0,0 +1,37 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents the detailed response model for a lecture hall. +/// +public class LectureHallDetailsResponse +{ + /// + /// Gets or sets the ID of the lecture hall. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the lecture hall. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the ID of the campus to which the lecture hall belongs. + /// + [Required] + public int CampusId { get; set; } + + /// + /// Gets or sets the name of the campus. + /// + public string? CampusName { get; set; } + + /// + /// Gets or sets the code of the campus. + /// + public string? CampusCode { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/LectureHallResponse.cs b/ApiDto/Responses/LectureHallResponse.cs new file mode 100644 index 0000000..6bb288f --- /dev/null +++ b/ApiDto/Responses/LectureHallResponse.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents the response model for a lecture hall. +/// +public class LectureHallResponse +{ + /// + /// Gets or sets the ID of the lecture hall. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the lecture hall. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the ID of the campus to which the lecture hall belongs. + /// + [Required] + public int CampusId { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/ProfessorResponse.cs b/ApiDto/Responses/ProfessorResponse.cs new file mode 100644 index 0000000..02361f9 --- /dev/null +++ b/ApiDto/Responses/ProfessorResponse.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses; + +/// +/// Represents information about a professor. +/// +public class ProfessorResponse +{ + /// + /// Gets or sets the unique identifier of the professor. + /// + [Required] + public int Id { get; set; } + + /// + /// Gets or sets the name of the professor. + /// + [Required] + public required string Name { get; set; } + + /// + /// Gets or sets the alternate name of the professor (optional). + /// + public string? AltName { get; set; } +} \ No newline at end of file diff --git a/ApiDto/Responses/Schedule/DisciplineScheduleResponse.cs b/ApiDto/Responses/Schedule/DisciplineScheduleResponse.cs new file mode 100644 index 0000000..bf4a337 --- /dev/null +++ b/ApiDto/Responses/Schedule/DisciplineScheduleResponse.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses.Schedule; + +/// +/// Represents information about a specific schedule entry for a professor. +/// +public class DisciplineScheduleInfo +{ + /// + /// Gets or sets the day of the week for the schedule entry. + /// + [Required] + public DayOfWeek DayOfWeek { get; set; } + + /// + /// Gets or sets the pair number for the schedule entry. + /// + [Required] + public int PairNumber { get; set; } + + /// + /// Gets or sets a value indicating whether the pair is on an even week. + /// + [Required] + public bool IsEven { get; set; } + + /// + /// Gets or sets the type of occupation for the schedule entry. + /// + [Required] + public required string TypeOfOccupation { get; set; } + + /// + /// Gets or sets the names of the group for the schedule entry. + /// + [Required] + + public required string Group { get; set; } + /// + /// Gets or sets the IDs of the group for the schedule entry. + /// + [Required] + public required int GroupId { get; set; } + + /// + /// Gets or sets the names of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHalls { get; set; } + + /// + /// Gets or sets the IDs of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHallsId { get; set; } + + /// + /// Gets or sets the names of the professors for the schedule entry. + /// + public required IEnumerable Professors { get; set; } + + /// + /// Gets or sets the IDs of the professors for the schedule entry. + /// + public required IEnumerable ProfessorsId { get; set; } + + /// + /// Gets or sets the names of the campuses for the schedule entry. + /// + public required IEnumerable Campus { get; set; } + + /// + /// Gets or sets the IDs of the campuses for the schedule entry. + /// + public required IEnumerable CampusId { get; set; } + + /// + /// Gets or sets the links to online meetings for the schedule entry. + /// + public required IEnumerable LinkToMeet { get; set; } +} + +/// +/// Represents a response containing schedule information for a professor. +/// +public class DisciplineScheduleResponse +{ + /// + /// Gets or sets the name of the discipline. + /// + [Required] + public required string Discipline { get; set; } + + /// + /// Gets or sets the ID of the discipline. + /// + [Required] + public required int DisciplineId { get; set; } + + /// + /// Gets or sets the schedules for the professor. + /// + [Required] + public required IEnumerable Schedules { get; set; } +} diff --git a/ApiDto/Responses/Schedule/GroupScheduleResponse.cs b/ApiDto/Responses/Schedule/GroupScheduleResponse.cs new file mode 100644 index 0000000..7fa13d1 --- /dev/null +++ b/ApiDto/Responses/Schedule/GroupScheduleResponse.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses.Schedule; + +/// +/// Represents information about a specific schedule entry for a group. +/// +public class GroupScheduleInfo +{ + /// + /// Gets or sets the day of the week for the schedule entry. + /// + [Required] + public DayOfWeek DayOfWeek { get; set; } + + /// + /// Gets or sets the pair number for the schedule entry. + /// + [Required] + public int PairNumber { get; set; } + + /// + /// Gets or sets a value indicating whether the pair is on an even week. + /// + [Required] + public bool IsEven { get; set; } + + /// + /// Gets or sets the name of the discipline for the schedule entry. + /// + [Required] + public required string Discipline { get; set; } + + /// + /// Gets or sets the ID of the discipline for the schedule entry. + /// + [Required] + public required int DisciplineId { get; set; } + + /// + /// Gets or sets the type of occupation for the schedule entry. + /// + [Required] + public required string TypeOfOccupation { get; set; } + + /// + /// Gets or sets the names of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHalls { get; set; } + + /// + /// Gets or sets the IDs of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHallsId { get; set; } + + /// + /// Gets or sets the names of the professors for the schedule entry. + /// + public required IEnumerable Professors { get; set; } + + /// + /// Gets or sets the IDs of the professors for the schedule entry. + /// + public required IEnumerable ProfessorsId { get; set; } + + /// + /// Gets or sets the names of the campuses for the schedule entry. + /// + public required IEnumerable Campus { get; set; } + + /// + /// Gets or sets the IDs of the campuses for the schedule entry. + /// + public required IEnumerable CampusId { get; set; } + + /// + /// Gets or sets the links to online meetings for the schedule entry. + /// + public required IEnumerable LinkToMeet { get; set; } +} + +/// +/// Represents a response containing schedule information for a group. +/// +public class GroupScheduleResponse +{ + /// + /// Gets or sets the name of the group. + /// + [Required] + public required string Group { get; set; } + + /// + /// Gets or sets the ID of the group. + /// + [Required] + public required int GroupId { get; set; } + + /// + /// Gets or sets the schedules for the group. + /// + [Required] + public required IEnumerable Schedules { get; set; } +} diff --git a/ApiDto/Responses/Schedule/LectureHallScheduleResponse.cs b/ApiDto/Responses/Schedule/LectureHallScheduleResponse.cs new file mode 100644 index 0000000..369a8f5 --- /dev/null +++ b/ApiDto/Responses/Schedule/LectureHallScheduleResponse.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses.Schedule; + +/// +/// Represents information about a specific schedule entry for a lecture hall. +/// +public class LectureHallScheduleInfo +{ + /// + /// Gets or sets the day of the week for the schedule entry. + /// + [Required] + public DayOfWeek DayOfWeek { get; set; } + + /// + /// Gets or sets the pair number for the schedule entry. + /// + [Required] + public int PairNumber { get; set; } + + /// + /// Gets or sets a value indicating whether the pair is on an even week. + /// + [Required] + public bool IsEven { get; set; } + + /// + /// Gets or sets the name of the discipline for the schedule entry. + /// + [Required] + public required string Discipline { get; set; } + + /// + /// Gets or sets the ID of the discipline for the schedule entry. + /// + [Required] + public required int DisciplineId { get; set; } + + /// + /// Gets or sets the type of occupation for the schedule entry. + /// + [Required] + public required string TypeOfOccupation { get; set; } + + /// + /// Gets or sets the names of the group for the schedule entry. + /// + [Required] + public required string Group { get; set; } + /// + /// Gets or sets the IDs of the group for the schedule entry. + /// + [Required] + public required int GroupId { get; set; } + + /// + /// Gets or sets the names of the campuses for the schedule entry. + /// + public required IEnumerable Campus { get; set; } + + /// + /// Gets or sets the IDs of the campuses for the schedule entry. + /// + public required IEnumerable CampusId { get; set; } + + /// + /// Gets or sets the names of the professors for the schedule entry. + /// + public required IEnumerable Professors { get; set; } + + /// + /// Gets or sets the IDs of the professors for the schedule entry. + /// + public required IEnumerable ProfessorsId { get; set; } + + /// + /// Gets or sets the links to online meetings for the schedule entry. + /// + public required IEnumerable LinkToMeet { get; set; } +} + +/// +/// Represents a response containing schedule information for a lecture hall. +/// +public class LectureHallScheduleResponse +{ + /// + /// Gets or sets the names of the lecture halls. + /// + public required string LectureHalls { get; set; } + + /// + /// Gets or sets the IDs of the lecture halls. + /// + public required int LectureHallsId { get; set; } + + /// + /// Gets or sets the schedules for the lecture hall. + /// + [Required] + public required IEnumerable Schedules { get; set; } +} diff --git a/ApiDto/Responses/Schedule/ProfessorScheduleResponse.cs b/ApiDto/Responses/Schedule/ProfessorScheduleResponse.cs new file mode 100644 index 0000000..3a53ebf --- /dev/null +++ b/ApiDto/Responses/Schedule/ProfessorScheduleResponse.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses.Schedule; + +/// +/// Represents information about a specific schedule entry for a professor. +/// +public class ProfessorScheduleInfo +{ + /// + /// Gets or sets the day of the week for the schedule entry. + /// + [Required] + public DayOfWeek DayOfWeek { get; set; } + + /// + /// Gets or sets the pair number for the schedule entry. + /// + [Required] + public int PairNumber { get; set; } + + /// + /// Gets or sets a value indicating whether the pair is on an even week. + /// + [Required] + public bool IsEven { get; set; } + + /// + /// Gets or sets the name of the discipline for the schedule entry. + /// + [Required] + public required string Discipline { get; set; } + + /// + /// Gets or sets the ID of the discipline for the schedule entry. + /// + [Required] + public required int DisciplineId { get; set; } + + /// + /// Gets or sets the type of occupation for the schedule entry. + /// + [Required] + public required string TypeOfOccupation { get; set; } + + /// + /// Gets or sets the names of the group for the schedule entry. + /// + [Required] + + public required string Group { get; set; } + /// + /// Gets or sets the IDs of the group for the schedule entry. + /// + [Required] + public required int GroupId { get; set; } + + /// + /// Gets or sets the names of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHalls { get; set; } + + /// + /// Gets or sets the IDs of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHallsId { get; set; } + + /// + /// Gets or sets the names of the campuses for the schedule entry. + /// + public required IEnumerable Campus { get; set; } + + /// + /// Gets or sets the IDs of the campuses for the schedule entry. + /// + public required IEnumerable CampusId { get; set; } + + /// + /// Gets or sets the links to online meetings for the schedule entry. + /// + public required IEnumerable LinkToMeet { get; set; } +} + +/// +/// Represents a response containing schedule information for a professor. +/// +public class ProfessorScheduleResponse +{ + /// + /// Gets or sets the name of the professor. + /// + [Required] + public required string Professor { get; set; } + + /// + /// Gets or sets the ID of the professor. + /// + [Required] + public required int ProfessorId { get; set; } + + /// + /// Gets or sets the schedules for the professor. + /// + [Required] + public required IEnumerable Schedules { get; set; } +} diff --git a/ApiDto/Responses/Schedule/ScheduleResponse.cs b/ApiDto/Responses/Schedule/ScheduleResponse.cs new file mode 100644 index 0000000..2a03178 --- /dev/null +++ b/ApiDto/Responses/Schedule/ScheduleResponse.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Mirea.Api.Dto.Responses.Schedule; + +/// +/// Represents a response object containing schedule information. +/// +public class ScheduleResponse +{ + /// + /// Gets or sets the day of the week for the schedule entry. + /// + [Required] + public DayOfWeek DayOfWeek { get; set; } + + /// + /// Gets or sets the pair number for the schedule entry. + /// + [Required] + public int PairNumber { get; set; } + + /// + /// Gets or sets a value indicating whether the pair is on an even week. + /// + [Required] + public bool IsEven { get; set; } + + /// + /// Gets or sets the name of the discipline for the schedule entry. + /// + [Required] + public required string Discipline { get; set; } + + /// + /// Gets or sets the ID of the discipline for the schedule entry. + /// + [Required] + public required int DisciplineId { get; set; } + + /// + /// Gets or sets the type of occupation for the schedule entry. + /// + [Required] + public required string TypeOfOccupation { get; set; } + + /// + /// Gets or sets the name of the group for the schedule entry. + /// + [Required] + public required string Group { get; set; } + + /// + /// Gets or sets the ID of the group for the schedule entry. + /// + [Required] + public required int GroupId { get; set; } + + /// + /// Gets or sets the names of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHalls { get; set; } + + /// + /// Gets or sets the IDs of the lecture halls for the schedule entry. + /// + public required IEnumerable LectureHallsId { get; set; } + + /// + /// Gets or sets the names of the professors for the schedule entry. + /// + public required IEnumerable Professors { get; set; } + + /// + /// Gets or sets the IDs of the professors for the schedule entry. + /// + public required IEnumerable ProfessorsId { get; set; } + + /// + /// Gets or sets the names of the campuses for the schedule entry. + /// + public required IEnumerable Campus { get; set; } + + /// + /// Gets or sets the IDs of the campuses for the schedule entry. + /// + public required IEnumerable CampusId { get; set; } + + /// + /// Gets or sets the links to online meetings for the schedule entry. + /// + public required IEnumerable LinkToMeet { get; set; } +} diff --git a/Application/Cqrs/Schedule/Queries/GetScheduleList/GetScheduleListQuery.cs b/Application/Cqrs/Schedule/Queries/GetScheduleList/GetScheduleListQuery.cs new file mode 100644 index 0000000..939e1c6 --- /dev/null +++ b/Application/Cqrs/Schedule/Queries/GetScheduleList/GetScheduleListQuery.cs @@ -0,0 +1,12 @@ +using MediatR; + +namespace Mirea.Api.DataAccess.Application.Cqrs.Schedule.Queries.GetScheduleList; + +public class GetScheduleListQuery : IRequest +{ + public int[]? GroupIds { get; set; } + public int[]? DisciplineIds { get; set; } + public int[]? LectureHallIds { get; set; } + public int[]? ProfessorIds { get; set; } + public bool? IsEven { get; set; } +} \ No newline at end of file diff --git a/Application/Cqrs/Schedule/Queries/GetScheduleList/GetScheduleListQueryHandler.cs b/Application/Cqrs/Schedule/Queries/GetScheduleList/GetScheduleListQueryHandler.cs new file mode 100644 index 0000000..ba08003 --- /dev/null +++ b/Application/Cqrs/Schedule/Queries/GetScheduleList/GetScheduleListQueryHandler.cs @@ -0,0 +1,87 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using Mirea.Api.DataAccess.Application.Interfaces.DbContexts.Schedule; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Mirea.Api.DataAccess.Application.Cqrs.Schedule.Queries.GetScheduleList; + +public class GetScheduleListQueryHandler(ILessonDbContext dbContext) : IRequestHandler +{ + public async Task Handle(GetScheduleListQuery request, CancellationToken cancellationToken) + { + var query = dbContext.Lessons.Include(l => l.LessonAssociations) + .ThenInclude(la => la.LectureHall) + .ThenInclude(lh => lh!.Campus) + .Include(l => l.LessonAssociations) + .ThenInclude(la => la.Professor) + .Include(l => l.Group) + .Include(l => l.TypeOfOccupation) + .Include(l => l.Discipline) + .AsQueryable(); + + if (request.IsEven != null) + query = query.Where(l => l.IsEven == request.IsEven); + + if (request.GroupIds != null && request.GroupIds.Length != 0) + query = query.Where(l => request.GroupIds.Contains(l.GroupId)); + + if (request.DisciplineIds != null && request.DisciplineIds.Length != 0) + query = query.Where(l => request.DisciplineIds.Contains(l.DisciplineId)); + + if (request.LectureHallIds != null && request.LectureHallIds.Length != 0) + query = query.Where(l => l.LessonAssociations!.Any(la => + la.LectureHallId != null && request.LectureHallIds.Contains(la.LectureHallId.Value))); + + if (request.ProfessorIds != null && request.ProfessorIds.Length != 0) + query = query.Where(l => + l.LessonAssociations!.Any(la => + la.ProfessorId != null && request.ProfessorIds.Contains(la.ProfessorId.Value))); + + var data = await query.ToArrayAsync(cancellationToken); + + var result = data.Select(l => new ScheduleLookupDto() + { + DayOfWeek = l.DayOfWeek, + PairNumber = l.PairNumber, + IsEven = l.IsEven, + TypeOfOccupation = l.TypeOfOccupation!.ShortName, + + Discipline = l.Discipline!.Name, + DisciplineId = l.DisciplineId, + + Group = l.Group!.Name, + GroupId = l.GroupId, + + LectureHalls = l.LessonAssociations! + .Where(la => !string.IsNullOrEmpty(la.LectureHall?.Name)) + .Select(la => la.LectureHall?.Name), + LectureHallsId = l.LessonAssociations! + .Where(la => la.LectureHallId != null) + .Select(la => la.LectureHallId), + + Campus = l.LessonAssociations! + .Where(la => !string.IsNullOrEmpty(la.LectureHall?.Campus?.CodeName)) + .Select(la => la.LectureHall?.Campus?.CodeName), + CampusId = l.LessonAssociations! + .Where(la => la.LectureHall?.Campus != null) + .Select(la => la.LectureHall?.CampusId), + + + Professors = l.LessonAssociations! + .Where(la => !string.IsNullOrEmpty(la.Professor?.Name)) + .Select(la => la.Professor?.Name), + ProfessorsId = l.LessonAssociations! + .Where(la => la.ProfessorId != null) + .Select(la => la.ProfessorId), + + LinkToMeet = l.LessonAssociations!.Select(la => la.LinkToMeet) + }).ToList(); + + return new ScheduleListVm + { + Schedules = result + }; + } +} \ No newline at end of file diff --git a/Application/Cqrs/Schedule/Queries/GetScheduleList/ScheduleListVm.cs b/Application/Cqrs/Schedule/Queries/GetScheduleList/ScheduleListVm.cs new file mode 100644 index 0000000..565e5b9 --- /dev/null +++ b/Application/Cqrs/Schedule/Queries/GetScheduleList/ScheduleListVm.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Mirea.Api.DataAccess.Application.Cqrs.Schedule.Queries.GetScheduleList; + +/// +/// Represents a view model for a list of schedules. +/// +public class ScheduleListVm +{ + /// + /// Gets or sets the list of schedules. + /// + public IList Schedules { get; set; } = new List(); +} \ No newline at end of file diff --git a/Application/Cqrs/Schedule/Queries/GetScheduleList/ScheduleLookupDto.cs b/Application/Cqrs/Schedule/Queries/GetScheduleList/ScheduleLookupDto.cs new file mode 100644 index 0000000..bd3808f --- /dev/null +++ b/Application/Cqrs/Schedule/Queries/GetScheduleList/ScheduleLookupDto.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; + +namespace Mirea.Api.DataAccess.Application.Cqrs.Schedule.Queries.GetScheduleList; + +/// +/// Represents a data transfer object for schedule lookup. +/// +public class ScheduleLookupDto +{ + /// + /// Gets or sets the day of the week. + /// + public DayOfWeek DayOfWeek { get; set; } + + /// + /// Gets or sets the pair number. + /// + public int PairNumber { get; set; } + + /// + /// Gets or sets a value indicating whether the pair is on an even week. + /// + public bool IsEven { get; set; } + + /// + /// Gets or sets the name of the discipline. + /// + public required string Discipline { get; set; } + + /// + /// Gets or sets the ID of the discipline. + /// + public required int DisciplineId { get; set; } + + /// + /// Gets or sets the type of occupation. + /// + public required string TypeOfOccupation { get; set; } + + /// + /// Gets or sets the name of the group. + /// + public required string Group { get; set; } + + /// + /// Gets or sets the ID of the group. + /// + public required int GroupId { get; set; } + + /// + /// Gets or sets the names of the lecture halls. + /// + public required IEnumerable LectureHalls { get; set; } + + /// + /// Gets or sets the IDs of the lecture halls. + /// + public required IEnumerable LectureHallsId { get; set; } + + /// + /// Gets or sets the names of the professors. + /// + public required IEnumerable Professors { get; set; } + + /// + /// Gets or sets the IDs of the professors. + /// + public required IEnumerable ProfessorsId { get; set; } + + /// + /// Gets or sets the names of the campuses. + /// + public required IEnumerable Campus { get; set; } + + /// + /// Gets or sets the IDs of the campuses. + /// + public required IEnumerable CampusId { get; set; } + + /// + /// Gets or sets the links to online meetings. + /// + public required IEnumerable LinkToMeet { get; set; } +} \ No newline at end of file diff --git a/Endpoint/Common/Attributes/BadRequestResponseAttribute.cs b/Endpoint/Common/Attributes/BadRequestResponseAttribute.cs new file mode 100644 index 0000000..85f9ed8 --- /dev/null +++ b/Endpoint/Common/Attributes/BadRequestResponseAttribute.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.Dto.Responses; +using System; + +namespace Mirea.Api.Endpoint.Common.Attributes; + +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +public class BadRequestResponseAttribute() : ProducesResponseTypeAttribute(typeof(ErrorResponse), StatusCodes.Status400BadRequest); \ No newline at end of file diff --git a/Endpoint/Common/Attributes/NotFoundResponseAttribute.cs b/Endpoint/Common/Attributes/NotFoundResponseAttribute.cs new file mode 100644 index 0000000..39527ea --- /dev/null +++ b/Endpoint/Common/Attributes/NotFoundResponseAttribute.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.Dto.Responses; +using System; + +namespace Mirea.Api.Endpoint.Common.Attributes; + +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +public class NotFoundResponseAttribute() : ProducesResponseTypeAttribute(typeof(ErrorResponse), StatusCodes.Status404NotFound); \ No newline at end of file diff --git a/Endpoint/ConfigureSwaggerOptions.cs b/Endpoint/Configuration/ConfigureSwaggerOptions.cs similarity index 96% rename from Endpoint/ConfigureSwaggerOptions.cs rename to Endpoint/Configuration/ConfigureSwaggerOptions.cs index 9b53140..39280bb 100644 --- a/Endpoint/ConfigureSwaggerOptions.cs +++ b/Endpoint/Configuration/ConfigureSwaggerOptions.cs @@ -5,7 +5,7 @@ using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System; -namespace Mirea.Api.Endpoint; +namespace Mirea.Api.Endpoint.Configuration; public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions { diff --git a/Endpoint/EnvironmentManager.cs b/Endpoint/Configuration/EnvironmentManager.cs similarity index 93% rename from Endpoint/EnvironmentManager.cs rename to Endpoint/Configuration/EnvironmentManager.cs index 3cbe859..cc2b201 100644 --- a/Endpoint/EnvironmentManager.cs +++ b/Endpoint/Configuration/EnvironmentManager.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Mirea.Api.Endpoint; +namespace Mirea.Api.Endpoint.Configuration; internal static class EnvironmentManager { diff --git a/Endpoint/SwaggerDefaultValues.cs b/Endpoint/Configuration/SwaggerDefaultValues.cs similarity index 93% rename from Endpoint/SwaggerDefaultValues.cs rename to Endpoint/Configuration/SwaggerDefaultValues.cs index d47c591..cefb307 100644 --- a/Endpoint/SwaggerDefaultValues.cs +++ b/Endpoint/Configuration/SwaggerDefaultValues.cs @@ -6,7 +6,7 @@ using System; using System.Linq; using System.Text.Json; -namespace Mirea.Api.Endpoint; +namespace Mirea.Api.Endpoint.Configuration; public class SwaggerDefaultValues : IOperationFilter { @@ -38,7 +38,7 @@ public class SwaggerDefaultValues : IOperationFilter { var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name); - parameter.Description ??= description.ModelMetadata?.Description; + parameter.Description ??= description.ModelMetadata.Description; if (parameter.Schema.Default == null && description.DefaultValue != null && diff --git a/Endpoint/Controllers/BaseController.cs b/Endpoint/Controllers/BaseController.cs new file mode 100644 index 0000000..82c4c7a --- /dev/null +++ b/Endpoint/Controllers/BaseController.cs @@ -0,0 +1,7 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Mirea.Api.Endpoint.Controllers; + +[ApiController] +[Route("api/[controller]/[action]")] +public class BaseController : ControllerBase; \ No newline at end of file diff --git a/Endpoint/Controllers/V1/BaseControllerV1.cs b/Endpoint/Controllers/V1/BaseControllerV1.cs new file mode 100644 index 0000000..6ebe1f3 --- /dev/null +++ b/Endpoint/Controllers/V1/BaseControllerV1.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Mirea.Api.Endpoint.Controllers.V1; + +[ApiVersion("1.0")] +[Produces("application/json")] +[Route("api/v{version:apiVersion}/[controller]/[action]")] +public class BaseControllerV1 : BaseController; \ No newline at end of file diff --git a/Endpoint/Controllers/V1/CampusController.cs b/Endpoint/Controllers/V1/CampusController.cs new file mode 100644 index 0000000..ae83834 --- /dev/null +++ b/Endpoint/Controllers/V1/CampusController.cs @@ -0,0 +1,61 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.Campus.Queries.GetCampusBasicInfoList; +using Mirea.Api.DataAccess.Application.Cqrs.Campus.Queries.GetCampusDetails; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Endpoint.Common.Attributes; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1 +{ + public class CampusController(IMediator mediator) : BaseControllerV1 + { + /// + /// Gets basic information about campuses. + /// + /// Basic information about campuses. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> Get() + { + var result = await mediator.Send(new GetCampusBasicInfoListQuery()); + + return Ok(result.Campuses + .Select(c => new CampusBasicInfoResponse() + { + Id = c.Id, + CodeName = c.CodeName, + FullName = c.FullName + }) + ); + } + + /// + /// Gets details of a specific campus by ID. + /// + /// Campus ID. + /// Details of the specified campus. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetDetails(int id) + { + var result = await mediator.Send(new GetCampusDetailsQuery() + { + Id = id + }); + + return Ok(new CampusDetailsResponse() + { + Id = result.Id, + CodeName = result.CodeName, + FullName = result.FullName, + Address = result.Address + }); + } + } +} diff --git a/Endpoint/Controllers/V1/DisciplineController.cs b/Endpoint/Controllers/V1/DisciplineController.cs new file mode 100644 index 0000000..056b208 --- /dev/null +++ b/Endpoint/Controllers/V1/DisciplineController.cs @@ -0,0 +1,65 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.Discipline.Queries.GetDisciplineDetails; +using Mirea.Api.DataAccess.Application.Cqrs.Discipline.Queries.GetDisciplineList; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Endpoint.Common.Attributes; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1 +{ + public class DisciplineController(IMediator mediator) : BaseControllerV1 + { + /// + /// Gets a paginated list of disciplines. + /// + /// Page number. Start from 0. + /// Number of items per page. + /// Paginated list of disciplines. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + public async Task>> Get([FromQuery] int? page, [FromQuery] int? pageSize) + { + var result = await mediator.Send(new GetDisciplineListQuery() + { + Page = page, + PageSize = pageSize + }); + + return Ok(result.Disciplines + .Select(d => new DisciplineResponse() + { + Id = d.Id, + Name = d.Name + }) + ); + } + + /// + /// Gets details of a specific discipline by ID. + /// + /// Discipline ID. + /// Details of the specified discipline. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetDetails(int id) + { + var result = await mediator.Send(new GetDisciplineInfoQuery() + { + Id = id + }); + + return Ok(new DisciplineResponse() + { + Id = result.Id, + Name = result.Name + }); + } + } +} diff --git a/Endpoint/Controllers/V1/FacultyController.cs b/Endpoint/Controllers/V1/FacultyController.cs new file mode 100644 index 0000000..3b4cd61 --- /dev/null +++ b/Endpoint/Controllers/V1/FacultyController.cs @@ -0,0 +1,69 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.Faculty.Queries.GetFacultyDetails; +using Mirea.Api.DataAccess.Application.Cqrs.Faculty.Queries.GetFacultyList; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Endpoint.Common.Attributes; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1 +{ + public class FacultyController(IMediator mediator) : BaseControllerV1 + { + /// + /// Gets a paginated list of faculties. + /// + /// Page number. Start from 0. + /// Number of items per page. + /// Paginated list of faculties. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + public async Task>> Get([FromQuery] int? page, [FromQuery] int? pageSize) + { + var result = await mediator.Send(new GetFacultyListQuery() + { + Page = page, + PageSize = pageSize + }); + + return Ok(result.Faculties + .Select(f => new FacultyResponse() + { + Id = f.Id, + Name = f.Name, + CampusId = f.CampusId + }) + ); + } + + /// + /// Gets details of a specific faculty by ID. + /// + /// Faculty ID. + /// Details of the specified faculty. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetDetails(int id) + { + var result = await mediator.Send(new GetFacultyInfoQuery() + { + Id = id + }); + + return Ok(new FacultyDetailsResponse() + { + Id = result.Id, + Name = result.Name, + CampusId = result.CampusId, + CampusCode = result.CampusCode, + CampusName = result.CampusName + }); + } + } +} diff --git a/Endpoint/Controllers/V1/GroupController.cs b/Endpoint/Controllers/V1/GroupController.cs new file mode 100644 index 0000000..cead029 --- /dev/null +++ b/Endpoint/Controllers/V1/GroupController.cs @@ -0,0 +1,108 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.Group.Queries.GetGroupDetails; +using Mirea.Api.DataAccess.Application.Cqrs.Group.Queries.GetGroupList; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Endpoint.Common.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1 +{ + public class GroupController(IMediator mediator) : BaseControllerV1 + { + private static int GetCourseNumber(string groupName) + { + var current = DateTime.Now; + if (!int.TryParse(groupName[2..], out var yearOfGroup) + && !int.TryParse(groupName.Split('-')[^1][..2], out yearOfGroup)) + return -1; + + // Convert a two-digit year to a four-digit one + yearOfGroup += current.Year / 100 * 100; + + return current.Year - yearOfGroup + (current.Month < 9 ? 0 : 1); + } + + /// + /// Retrieves a list of groups. + /// + /// The page number for pagination (optional). + /// The page size for pagination (optional). + /// A list of groups. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + public async Task>> Get([FromQuery] int? page, [FromQuery] int? pageSize) + { + var result = await mediator.Send(new GetGroupListQuery() + { + Page = page, + PageSize = pageSize + }); + + return Ok(result.Groups + .Select(g => new GroupResponse() + { + Id = g.Id, + Name = g.Name, + FacultyId = g.FacultyId, + CourseNumber = GetCourseNumber(g.Name) + }) + ); + } + + /// + /// Retrieves detailed information about a specific group. + /// + /// The ID of the group to retrieve. + /// Detailed information about the group. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetDetails(int id) + { + var result = await mediator.Send(new GetGroupInfoQuery() + { + Id = id + }); + + return Ok(new GroupDetailsResponse() + { + Id = result.Id, + Name = result.Name, + FacultyId = result.FacultyId, + FacultyName = result.Faculty, + CourseNumber = GetCourseNumber(result.Name) + }); + } + + /// + /// Retrieves a list of groups by faculty ID. + /// + /// The ID of the faculty. + /// A list of groups belonging to the specified faculty. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task>> GetByFaculty(int id) + { + var result = await mediator.Send(new GetGroupListQuery()); + + return Ok(result.Groups + .Where(g => g.FacultyId == id) + .Select(g => new GroupResponse() + { + Id = g.Id, + Name = g.Name, + CourseNumber = GetCourseNumber(g.Name), + FacultyId = g.FacultyId + })); + } + } +} diff --git a/Endpoint/Controllers/V1/LectureHallController.cs b/Endpoint/Controllers/V1/LectureHallController.cs new file mode 100644 index 0000000..de2f21f --- /dev/null +++ b/Endpoint/Controllers/V1/LectureHallController.cs @@ -0,0 +1,84 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.LectureHall.Queries.GetLectureHallDetails; +using Mirea.Api.DataAccess.Application.Cqrs.LectureHall.Queries.GetLectureHallList; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Endpoint.Common.Attributes; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1 +{ + public class LectureHallController(IMediator mediator) : BaseControllerV1 + { + /// + /// Retrieves a list of all lecture halls. + /// + /// A list of lecture halls. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> Get() + { + var result = await mediator.Send(new GetLectureHallListQuery()); + + return Ok(result.LectureHalls + .Select(l => new LectureHallResponse() + { + Id = l.Id, + Name = l.Name, + CampusId = l.CampusId + }) + ); + } + + /// + /// Retrieves details of a specific lecture hall by its ID. + /// + /// The ID of the lecture hall to retrieve. + /// The details of the specified lecture hall. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetDetails(int id) + { + var result = await mediator.Send(new GetLectureHallInfoQuery() + { + Id = id + }); + + return Ok(new LectureHallDetailsResponse() + { + Id = result.Id, + Name = result.Name, + CampusId = result.CampusId, + CampusCode = result.CampusCode, + CampusName = result.CampusName + }); + } + + /// + /// Retrieves a list of lecture halls by campus ID. + /// + /// The ID of the campus. + /// A list of lecture halls in the specified campus. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task>> GetByCampus(int id) + { + var result = await mediator.Send(new GetLectureHallListQuery()); + + return Ok(result.LectureHalls.Where(l => l.CampusId == id) + .Select(l => new LectureHallResponse() + { + Id = l.Id, + Name = l.Name, + CampusId = l.CampusId + })); + } + } +} diff --git a/Endpoint/Controllers/V1/ProfessorController.cs b/Endpoint/Controllers/V1/ProfessorController.cs new file mode 100644 index 0000000..5a9053a --- /dev/null +++ b/Endpoint/Controllers/V1/ProfessorController.cs @@ -0,0 +1,66 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.Professor.Queries.GetProfessorDetails; +using Mirea.Api.DataAccess.Application.Cqrs.Professor.Queries.GetProfessorList; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Endpoint.Common.Attributes; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1; + +public class ProfessorController(IMediator mediator) : BaseControllerV1 +{ + /// + /// Retrieves a list of professors. + /// + /// The page number for pagination (optional). + /// The page size for pagination (optional). + /// A list of professors. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + public async Task>> Get([FromQuery] int? page, [FromQuery] int? pageSize) + { + var result = await mediator.Send(new GetProfessorListQuery() + { + Page = page, + PageSize = pageSize + }); + + return Ok(result.Professors + .Select(p => new ProfessorResponse() + { + Id = p.Id, + Name = p.Name, + AltName = p.AltName + }) + ); + } + + /// + /// Retrieves detailed information about a specific professor. + /// + /// The ID of the professor to retrieve. + /// Detailed information about the professor. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetDetails(int id) + { + var result = await mediator.Send(new GetProfessorInfoQuery() + { + Id = id + }); + + return Ok(new ProfessorResponse() + { + Id = result.Id, + Name = result.Name, + AltName = result.AltName + }); + } +} \ No newline at end of file diff --git a/Endpoint/Controllers/V1/ScheduleController.cs b/Endpoint/Controllers/V1/ScheduleController.cs new file mode 100644 index 0000000..43b47ad --- /dev/null +++ b/Endpoint/Controllers/V1/ScheduleController.cs @@ -0,0 +1,304 @@ +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Mirea.Api.DataAccess.Application.Cqrs.Schedule.Queries.GetScheduleList; +using Mirea.Api.Dto.Requests; +using Mirea.Api.Dto.Responses; +using Mirea.Api.Dto.Responses.Schedule; +using Mirea.Api.Endpoint.Common.Attributes; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1; + +public class ScheduleController(IMediator mediator) : BaseControllerV1 +{ + /// + /// Retrieves schedules based on various filters. + /// + /// The request object containing filter criteria. + /// A list of schedules matching the filter criteria. + [HttpPost] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [BadRequestResponse] + [NotFoundResponse] + public async Task>> Get([FromBody] ScheduleRequest request) + + { + if ((request.Groups == null || !request.Groups.Any()) && + (request.Disciplines == null || !request.Disciplines.Any()) && + (request.Professors == null || !request.Professors.Any()) && + (request.LectureHalls == null || !request.LectureHalls.Any())) + { + return BadRequest(new ErrorResponse() + { + Error = "At least one of the arguments must be selected." + + (request.IsEven.HasValue + ? $" \"{nameof(request.IsEven)}\" is not a strong argument" + : string.Empty), + Code = StatusCodes.Status400BadRequest + }); + } + + var result = (await mediator.Send(new GetScheduleListQuery() + { + IsEven = request.IsEven, + DisciplineIds = request.Disciplines, + GroupIds = request.Groups, + LectureHallIds = request.LectureHalls, + ProfessorIds = request.Professors + })).Schedules; + + if (result.Count == 0) NoContent(); + + return Ok(result.Select(s => new ScheduleResponse() + { + DayOfWeek = s.DayOfWeek, + PairNumber = s.PairNumber, + IsEven = s.IsEven, + Discipline = s.Discipline, + DisciplineId = s.DisciplineId, + TypeOfOccupation = s.TypeOfOccupation, + Group = s.Group, + GroupId = s.GroupId, + LectureHalls = s.LectureHalls, + LectureHallsId = s.LectureHallsId, + Professors = s.Professors, + ProfessorsId = s.ProfessorsId, + Campus = s.Campus, + CampusId = s.CampusId, + LinkToMeet = s.LinkToMeet + })); + + } + + /// + /// Retrieves schedules for a specific group based on various filters. + /// + /// The ID of the group. + /// A value indicating whether to retrieve schedules for even weeks. + /// An array of discipline IDs. + /// An array of professor IDs. + /// An array of lecture hall IDs. + /// A response containing schedules for the specified group. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetByGroup(int id, + [FromQuery] bool? isEven = null, + [FromQuery] int[]? disciplines = null, + [FromQuery] int[]? professors = null, + [FromQuery] int[]? lectureHalls = null) + + { + var result = (await mediator.Send(new GetScheduleListQuery() + { + IsEven = isEven, + DisciplineIds = disciplines, + GroupIds = [id], + LectureHallIds = lectureHalls, + ProfessorIds = professors + })).Schedules; + + if (result.Count == 0) NoContent(); + + return Ok(new GroupScheduleResponse() + { + Group = result[0].Group, + GroupId = result[0].GroupId, + Schedules = result.Select(g => new GroupScheduleInfo() + { + DayOfWeek = g.DayOfWeek, + PairNumber = g.PairNumber, + IsEven = g.IsEven, + Discipline = g.Discipline, + DisciplineId = g.DisciplineId, + TypeOfOccupation = g.TypeOfOccupation, + LectureHalls = g.LectureHalls, + LectureHallsId = g.LectureHallsId, + Professors = g.Professors, + ProfessorsId = g.ProfessorsId, + Campus = g.Campus, + CampusId = g.CampusId, + LinkToMeet = g.LinkToMeet + }) + }); + } + + /// + /// Retrieves schedules for a specific professor based on various filters. + /// + /// The ID of the professor. + /// A value indicating whether to retrieve schedules for even weeks. + /// An array of discipline IDs. + /// An array of group IDs. + /// An array of lecture hall IDs. + /// A response containing schedules for the specified professor. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetByProfessor(int id, + [FromQuery] bool? isEven = null, + [FromQuery] int[]? disciplines = null, + [FromQuery] int[]? groups = null, + [FromQuery] int[]? lectureHalls = null) + + { + var result = (await mediator.Send(new GetScheduleListQuery() + { + IsEven = isEven, + DisciplineIds = disciplines, + GroupIds = groups, + LectureHallIds = lectureHalls, + ProfessorIds = [id] + })).Schedules; + + if (result.Count == 0) NoContent(); + + return Ok(new ProfessorScheduleResponse() + { + Professor = result.Select(professor => + professor.Professors.FirstOrDefault(x => !string.IsNullOrEmpty(x)) + ).First()!, + ProfessorId = result.Select(professor => + professor.ProfessorsId.FirstOrDefault(x => x != null) + ).First()!.Value, + Schedules = result.Select(p => new ProfessorScheduleInfo() + { + DayOfWeek = p.DayOfWeek, + PairNumber = p.PairNumber, + IsEven = p.IsEven, + Discipline = p.Discipline, + DisciplineId = p.DisciplineId, + TypeOfOccupation = p.TypeOfOccupation, + Group = p.Group, + GroupId = p.GroupId, + LectureHalls = p.LectureHalls, + LectureHallsId = p.LectureHallsId, + Campus = p.Campus, + CampusId = p.CampusId, + LinkToMeet = p.LinkToMeet + }) + }); + } + + /// + /// Retrieves schedules for a specific lecture hall based on various filters. + /// + /// The ID of the lecture hall. + /// A value indicating whether to retrieve schedules for even weeks. + /// An array of discipline IDs. + /// An array of professor IDs. + /// An array of group IDs. + /// A response containing schedules for the specified lecture hall. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetByLectureHall(int id, + [FromQuery] bool? isEven = null, + [FromQuery] int[]? disciplines = null, + [FromQuery] int[]? groups = null, + [FromQuery] int[]? professors = null) + + { + var result = (await mediator.Send(new GetScheduleListQuery() + { + IsEven = isEven, + DisciplineIds = disciplines, + GroupIds = groups, + LectureHallIds = [id], + ProfessorIds = professors + })).Schedules; + + if (result.Count == 0) NoContent(); + + return Ok(new LectureHallScheduleResponse() + { + LectureHalls = result.Select(lectureHall => + lectureHall.LectureHalls.FirstOrDefault(x => !string.IsNullOrEmpty(x)) + ).First()!, + LectureHallsId = result.Select(lectureHall => + lectureHall.LectureHallsId.FirstOrDefault(x => x != null) + ).First()!.Value, + Schedules = result.Select(l => new LectureHallScheduleInfo() + { + DayOfWeek = l.DayOfWeek, + PairNumber = l.PairNumber, + IsEven = l.IsEven, + Discipline = l.Discipline, + DisciplineId = l.DisciplineId, + TypeOfOccupation = l.TypeOfOccupation, + Group = l.Group, + GroupId = l.GroupId, + Professors = l.Professors, + ProfessorsId = l.ProfessorsId, + Campus = l.Campus, + CampusId = l.CampusId, + LinkToMeet = l.LinkToMeet + }) + }); + } + + /// + /// Retrieves schedules for a specific discipline based on various filters. + /// + /// The ID of the discipline. + /// A value indicating whether to retrieve schedules for even weeks. + /// An array of group IDs. + /// An array of professor IDs. + /// An array of lecture hall IDs. + /// A response containing schedules for the specified discipline. + [HttpGet("{id:int}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [BadRequestResponse] + [NotFoundResponse] + public async Task> GetByDiscipline(int id, + [FromQuery] bool? isEven = null, + [FromQuery] int[]? groups = null, + [FromQuery] int[]? professors = null, + [FromQuery] int[]? lectureHalls = null) + + { + var result = (await mediator.Send(new GetScheduleListQuery() + { + IsEven = isEven, + DisciplineIds = [id], + GroupIds = groups, + LectureHallIds = [id], + ProfessorIds = professors + })).Schedules; + + if (result.Count == 0) NoContent(); + + return Ok(new DisciplineScheduleResponse() + { + Discipline = result[0].Discipline, + DisciplineId = result[0].DisciplineId, + Schedules = result.Select(d => new DisciplineScheduleInfo() + { + DayOfWeek = d.DayOfWeek, + PairNumber = d.PairNumber, + IsEven = d.IsEven, + TypeOfOccupation = d.TypeOfOccupation, + Group = d.Group, + GroupId = d.GroupId, + LectureHalls = d.LectureHalls, + LectureHallsId = d.LectureHallsId, + Professors = d.Professors, + ProfessorsId = d.ProfessorsId, + Campus = d.Campus, + CampusId = d.CampusId, + LinkToMeet = d.LinkToMeet + }) + }); + } +} \ No newline at end of file diff --git a/Endpoint/Endpoint.csproj b/Endpoint/Endpoint.csproj index 84dcfc2..0191a2e 100644 --- a/Endpoint/Endpoint.csproj +++ b/Endpoint/Endpoint.csproj @@ -28,6 +28,7 @@ + diff --git a/Endpoint/Program.cs b/Endpoint/Program.cs index 920ce15..3607500 100644 --- a/Endpoint/Program.cs +++ b/Endpoint/Program.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Mirea.Api.DataAccess.Application; using Mirea.Api.DataAccess.Persistence; +using Mirea.Api.Endpoint.Configuration; using Mirea.Api.Endpoint.Properties; using Swashbuckle.AspNetCore.SwaggerGen; using System;