Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Grades Assigning #62

Merged
merged 33 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
feaeb33
Redesign a model for assigned grade
romandykyi Dec 9, 2023
5a00305
Add ActivityType entity and its DTOs
romandykyi Dec 10, 2023
acf7dd3
Implement `ActivityType` service
romandykyi Dec 10, 2023
2bd6970
Implement activity types endpoints
romandykyi Dec 10, 2023
52006a9
Configure test data for `ActivityType`
romandykyi Dec 10, 2023
4de55e6
Update README.md
romandykyi Dec 10, 2023
85631fc
Add DTOs for assigned grades
romandykyi Dec 11, 2023
0a0d339
Make the assigned grades validator class generic
romandykyi Dec 11, 2023
0cb4264
Add DTOs for ClassGrade and validation
romandykyi Dec 11, 2023
53c7e87
Fix error in a test
romandykyi Dec 11, 2023
ae909d2
Create `IAssignedGradesService` interface
romandykyi Dec 11, 2023
8af09cc
Manage namespaces
romandykyi Dec 12, 2023
05c6679
Merge branch 'master' into implement-grades-assigning
romandykyi Dec 25, 2023
b97b853
Merge `ClassGrade` and `AssignedGrade`
romandykyi Dec 25, 2023
5a2d47f
Add `AssignedGrades` table
romandykyi Dec 25, 2023
346663e
Add `AssignedGradeUpdateDto`
romandykyi Dec 25, 2023
23c8080
Implement `AssignedGradesService`
romandykyi Dec 25, 2023
7a71fc2
Implement `AssignedGradesFilter`
romandykyi Dec 25, 2023
f0d17ed
Refactor authorization handlers
romandykyi Dec 26, 2023
a9477f5
Update comments
romandykyi Dec 26, 2023
2188767
Refactor `AssignedGradesFilter`
romandykyi Dec 26, 2023
fa0336b
Add an additional method for `GroupsService`
romandykyi Dec 26, 2023
b876a6b
Remove unnecessary code
romandykyi Dec 26, 2023
64c3add
Add `Async` suffix
romandykyi Dec 26, 2023
97afc7a
Forbid students view another students via groups or semesters
romandykyi Dec 26, 2023
c7c79e1
Implement some assigned grades get methods
romandykyi Dec 26, 2023
bde1ca9
Implement `IAssignedGradesService.GetAssignerIdAsync`
romandykyi Dec 26, 2023
5c31126
Remove redundant includes
romandykyi Dec 26, 2023
2ed6766
Update return type
romandykyi Dec 26, 2023
3b230b2
Fix dto property name
romandykyi Dec 26, 2023
c5f211a
Implement controller for assigned grades
romandykyi Dec 26, 2023
beeeda5
Fix false negatives in tests
romandykyi Dec 26, 2023
8f1e0f9
Fix accidental change
romandykyi Dec 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implement AssignedGradesFilter
  • Loading branch information
romandykyi committed Dec 25, 2023
commit 7a71fc277a033a37c66e14b7def4e161fec56044
220 changes: 220 additions & 0 deletions EUniversity.Tests/Filters/AssignedGradesFilterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
using EUniversity.Core.Models;
using EUniversity.Core.Models.University;
using EUniversity.Core.Models.University.Grades;
using EUniversity.Infrastructure.Filters;
using System.ComponentModel;

namespace EUniversity.Tests.Filters;

public class AssignedGradesFilterTests
{
private static readonly Grade TestGrade1 = new()
{
Id = 100,
Name = "5"
};
private static readonly Grade TestGrade2 = new()
{
Id = 101,
Name = "2"
};
private static readonly ApplicationUser TestTeacher1 = new()
{
Id = "test-teacher-1"
};
private static readonly ApplicationUser TestTeacher2 = new()
{
Id = "test-teacher-2"
};
private static readonly ApplicationUser TestStudent1 = new()
{
Id = "test-student-1"
};
private static readonly ApplicationUser TestStudent2 = new()
{
Id = "test-student-2"
};
private static readonly Group TestGroup1 = new()
{
Id = 200,
Name = "Group1"
};
private static readonly Group TestGroup2 = new()
{
Id = 201,
Name = "Group2"
};
private static readonly ActivityType TestActivityType = new()
{
Id = 200,
Name = "Exam"
};

private static readonly AssignedGrade[] TestData =
{
new()
{
Id = 500,
Grade = TestGrade1, GradeId = TestGrade1.Id,
AssignerId = TestTeacher1.Id, ReassignerId = TestTeacher2.Id,
StudentId = TestStudent1.Id,
GroupId = TestGroup2.Id,
ActivityTypeId = TestActivityType.Id
},
new()
{
Id = 501,
Grade = TestGrade1, GradeId = TestGrade1.Id,
AssignerId = TestTeacher2.Id,
StudentId = TestStudent1.Id,
GroupId = TestGroup1.Id,
ActivityTypeId = TestActivityType.Id
},
new()
{
Id = 502,
Grade = TestGrade2, GradeId = TestGrade2.Id,
AssignerId = TestTeacher1.Id, ReassignerId = TestTeacher2.Id,
StudentId = TestStudent1.Id,
GroupId = TestGroup1.Id
},
new()
{
Id = 503,
Grade = TestGrade2, GradeId = TestGrade2.Id,
AssignerId = TestTeacher2.Id,
StudentId = TestStudent1.Id,
GroupId = TestGroup2.Id,
ActivityTypeId = TestActivityType.Id
},
new()
{
Id = 504,
Grade = TestGrade2, GradeId = TestGrade2.Id,
AssignerId = TestTeacher1.Id, ReassignerId = TestTeacher2.Id,
StudentId = TestStudent2.Id,
GroupId = TestGroup1.Id,
ActivityTypeId = TestActivityType.Id
},
new()
{
Id = 505,
Grade = TestGrade2, GradeId = TestGrade2.Id,
AssignerId = TestTeacher2.Id, ReassignerId = TestTeacher1.Id,
StudentId = TestStudent1.Id,
GroupId = TestGroup1.Id
},
};

[Test]
public void AssignerIdSpecified_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(AssignerId: TestTeacher1.Id);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 500, 502, 504 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}

[Test]
public void ReassignerIdSpecified_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(ReassignerId: TestTeacher1.Id);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 505 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}

[Test]
public void StudentIdSpecified_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(StudentId: TestStudent2.Id);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 504 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}

[Test]
public void GroupIdSpecified_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(GroupId: TestGroup2.Id);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 500, 503 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}

[Test]
public void ActivityTypeId_Zero_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(ActivityTypeId: 0);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 502, 505 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}

[Test]
public void ActivityTypeIdSpecified_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(ActivityTypeId: TestActivityType.Id);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 500, 501, 503, 504 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}

[Test]
public void GradeIdSpecified_ReturnsFilteredQuery()
{
// Arrange
AssignedGradesFilterProperties properties = new(GradeId: TestGrade1.Id);
AssignedGradesFilter filter = new(properties);
int[] expectedIds = { 500, 501 };

// Act
var actualIds = filter.Apply(TestData.AsQueryable())
.Select(x => x.Id);

// Assert
Assert.That(actualIds, Is.EquivalentTo(expectedIds));
}
}
56 changes: 56 additions & 0 deletions Infrastructure/Filters/AssignedGradesFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using EUniversity.Core.Filters;
using EUniversity.Core.Models.University.Grades;

namespace EUniversity.Infrastructure.Filters;

/// <summary>
/// Filter for assigned grades.
/// </summary>
public class AssignedGradesFilter : IFilter<AssignedGrade>
{
public AssignedGradesFilterProperties Properties { get; }

public AssignedGradesFilter(AssignedGradesFilterProperties properties)
{
Properties = properties;
}

/// <summary>
/// Applies the assigned grades filter and sorts results by assignation date.
/// </summary>
/// <param name="query">The query that needs to be filtered.</param>
/// <returns>
/// Filtered query with assigned grades which satisfy filter properties and sorted
/// by assignation date.
/// </returns>
public IQueryable<AssignedGrade> Apply(IQueryable<AssignedGrade> query)
{
if (Properties.AssignerId != null)
{
query = query.Where(g => g.AssignerId == Properties.AssignerId);
}
if (Properties.ReassignerId != null)
{
query = query.Where(g => g.ReassignerId == Properties.ReassignerId);
}
if (Properties.StudentId != null)
{
query = query.Where(g => g.StudentId == Properties.StudentId);
}
if (Properties.GroupId != null)
{
query = query.Where(g => g.GroupId == Properties.GroupId);
}
if (Properties.ActivityTypeId != null)
{
query = Properties.ActivityTypeId != 0 ?
query.Where(g => g.ActivityTypeId == Properties.ActivityTypeId) :
query.Where(g => g.ActivityTypeId == null);
}
if (Properties.GradeId != null)
{
query = query.Where(g => g.GradeId == Properties.GradeId);
}
return query.OrderByDescending(g => g.CreationDate);
}
}
15 changes: 15 additions & 0 deletions Infrastructure/Filters/AssignedGradesFilterProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace EUniversity.Infrastructure.Filters;

/// <summary>
/// Properties for <see cref="AssignedGradesFilter" />
/// </summary>
/// <param name="AssignerId">An optional ID of an assigner to filter by.</param>
/// <param name="ReassignerId">An optional ID of a reassigner to filter by.</param>
/// <param name="StudentId">An optional ID of an assignee student to filter by.</param>
/// <param name="GroupId">An optional ID of a gorup to filter by.</param>
/// <param name="ActivityTypeId">An optional ID of an activity type to filter by. If 0, then grades without activity type will be returned.</param>
/// <param name="GradeId">An optional ID of a grade to filter by.</param>
public record AssignedGradesFilterProperties(
string? AssignerId = null, string? ReassignerId = null,
string? StudentId = null, int? GroupId = null,
int? ActivityTypeId = null, int? GradeId = null);