diff --git a/CandidateReviewBusinessLogic/BusinessLogic/AssessmentCriterionLogic.cs b/CandidateReviewBusinessLogic/BusinessLogic/AssessmentCriterionLogic.cs new file mode 100644 index 0000000..bcfd15e --- /dev/null +++ b/CandidateReviewBusinessLogic/BusinessLogic/AssessmentCriterionLogic.cs @@ -0,0 +1,78 @@ +using CandidateReviewContracts.BindingModels; +using CandidateReviewContracts.BusinessLogicsContracts; +using CandidateReviewContracts.SearchModels; +using CandidateReviewContracts.StoragesContracts; +using CandidateReviewContracts.ViewModels; +using CandidateReviewDatabaseImplement.Implements; +using CandidateReviewDatabaseImplement.Models; +using Microsoft.Extensions.Logging; +using System.Xml.Linq; + +namespace CandidateReviewBusinessLogic.BusinessLogic +{ + public class AssessmentCriterionLogic : IAssessmentCriterionLogic + { + private readonly ILogger _logger; + private readonly IAssessmentCriterionStorage _assessmentCriterionStorage; + private readonly ICriterionStorage _criterionStorage; + + public AssessmentCriterionLogic(ILogger logger, IAssessmentCriterionStorage assessmentCriterionStorage, ICriterionStorage criterionStorage) + { + _logger = logger; + _assessmentCriterionStorage = assessmentCriterionStorage; + _criterionStorage = criterionStorage; + } + public bool Create(AssessmentCriterionModel model) + { + if (_assessmentCriterionStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + + public bool Delete(AssessmentCriterionModel model) + { + throw new NotImplementedException(); + } + + public AssessmentCriterionViewModel? ReadElement(AssessmentCriterionSearchModel model) + { + throw new NotImplementedException(); + } + + public List? ReadList(AssessmentCriterionSearchModel? model) + { + var list = model == null ? _assessmentCriterionStorage.GetFullList() : _assessmentCriterionStorage.GetFilteredList(model); + + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + + List result = new(); + foreach (var item in list) + { + var viewModel = new AssessmentCriterionViewModel + { + Id = item.Id, + AssessmentId = item.AssessmentId, + CriterionId = item.CriterionId, + CriterionName = _criterionStorage.GetElement(new CriterionSearchModel { Id = item.CriterionId }).Name, + Value = item.Value + }; + result.Add(viewModel); + } + + _logger.LogInformation("ReadList. Count: {Count}", result.Count); + return result; + } + + public bool Update(AssessmentCriterionModel model) + { + throw new NotImplementedException(); + } + } +} diff --git a/CandidateReviewBusinessLogic/BusinessLogic/AssessmentLogic.cs b/CandidateReviewBusinessLogic/BusinessLogic/AssessmentLogic.cs index 2d6ee60..14bdfab 100644 --- a/CandidateReviewBusinessLogic/BusinessLogic/AssessmentLogic.cs +++ b/CandidateReviewBusinessLogic/BusinessLogic/AssessmentLogic.cs @@ -15,13 +15,15 @@ namespace CandidateReviewBusinessLogic.BusinessLogic private readonly IAssessmentStorage _assessmentStorage; private readonly IUserStorage _userStorage; private readonly ICriterionStorage _criterionStorage; + private readonly IAssessmentCriterionStorage _assessmentCriterionStorage; - public AssessmentLogic(ILogger logger, IAssessmentStorage assessmentStorage, IUserStorage userStorage, ICriterionStorage criterionStorage) + public AssessmentLogic(ILogger logger, IAssessmentStorage assessmentStorage, IUserStorage userStorage, ICriterionStorage criterionStorage, IAssessmentCriterionStorage assessmentCriterionStorage) { _logger = logger; _assessmentStorage = assessmentStorage; _userStorage = userStorage; _criterionStorage = criterionStorage; + _assessmentCriterionStorage = assessmentCriterionStorage; } public int? Create(AssessmentBindingModel model) @@ -36,6 +38,8 @@ namespace CandidateReviewBusinessLogic.BusinessLogic return id; } + + public bool Delete(AssessmentBindingModel model) { CheckModel(model, false); @@ -74,8 +78,22 @@ namespace CandidateReviewBusinessLogic.BusinessLogic return null; } - _logger.LogInformation("ReadList. Count: {Count}", list.Count); - return list; + List result = new(); + foreach (var item in list) + { + var viewModel = new AssessmentViewModel + { + Id = item.Id, + ResumeId = item.ResumeId, + UserId = item.UserId, + UserName = _userStorage.GetElement(new UserSearchModel { Id = item.UserId }).Name + " " + _userStorage.GetElement(new UserSearchModel { Id = item.UserId }).Surname, + Comment = item.Comment + }; + result.Add(viewModel); + } + + _logger.LogInformation("ReadList. Count: {Count}", result.Count); + return result; } public bool Update(AssessmentBindingModel model) diff --git a/CandidateReviewBusinessLogic/BusinessLogic/ResumeLogic.cs b/CandidateReviewBusinessLogic/BusinessLogic/ResumeLogic.cs index c8acf0c..7bba688 100644 --- a/CandidateReviewBusinessLogic/BusinessLogic/ResumeLogic.cs +++ b/CandidateReviewBusinessLogic/BusinessLogic/ResumeLogic.cs @@ -66,8 +66,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic ResumeId = a.ResumeId, UserName = a.UserName, UserId = a.UserId, - Comment = a.Comment, - AssessmentCriterions = a.AssessmentCriterions + Comment = a.Comment }).ToList() ?? new List(); var resumeViewModel = new ResumeViewModel @@ -109,8 +108,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic ResumeId = a.ResumeId, UserId = a.UserId, UserName = a.UserName, - Comment = a.Comment, - AssessmentCriterions = a.AssessmentCriterions + Comment = a.Comment }).ToList() ?? new List(); var resumeViewModel = new ResumeViewModel diff --git a/CandidateReviewClientApp/APIClient.cs b/CandidateReviewClientApp/APIClient.cs index 970a44f..e8b1716 100644 --- a/CandidateReviewClientApp/APIClient.cs +++ b/CandidateReviewClientApp/APIClient.cs @@ -8,18 +8,18 @@ namespace CandidateReviewClientApp { public class APIClient { - private static readonly HttpClient _user = new(); + private static readonly HttpClient _client = new(); public static UserViewModel? User { get; set; } = null; public static CompanyViewModel? Company { get; set; } = null; public static void Connect(IConfiguration configuration) { - _user.BaseAddress = new Uri(configuration["IPAddress"]); - _user.DefaultRequestHeaders.Accept.Clear(); - _user.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _client.BaseAddress = new Uri(configuration["IPAddress"]); + _client.DefaultRequestHeaders.Accept.Clear(); + _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); } public static T? GetRequest(string requestUrl) { - var response = _user.GetAsync(requestUrl); + var response = _client.GetAsync(requestUrl); var result = response.Result.Content.ReadAsStringAsync().Result; if (response.Result.IsSuccessStatusCode) { @@ -36,7 +36,7 @@ namespace CandidateReviewClientApp try { // Асинхронный запрос - var response = await _user.GetAsync(requestUrl); + var response = await _client.GetAsync(requestUrl); // Чтение содержимого ответа var result = await response.Content.ReadAsStringAsync(); @@ -64,7 +64,7 @@ namespace CandidateReviewClientApp { var json = JsonConvert.SerializeObject(model); var data = new StringContent(json, Encoding.UTF8, "application/json"); - var response = _user.PostAsync(requestUrl, data); + var response = _client.PostAsync(requestUrl, data); var result = response.Result.Content.ReadAsStringAsync().Result; if (!response.Result.IsSuccessStatusCode) { @@ -77,7 +77,7 @@ namespace CandidateReviewClientApp var json = JsonConvert.SerializeObject(model); var data = new StringContent(json, Encoding.UTF8, "application/json"); - var response = await _user.PostAsync(requestUrl, data); + var response = await _client.PostAsync(requestUrl, data); if (!response.IsSuccessStatusCode) { @@ -103,7 +103,7 @@ namespace CandidateReviewClientApp var json = JsonConvert.SerializeObject(model); var data = new StringContent(json, Encoding.UTF8, "application/json"); - var response = await _user.PostAsync(requestUrl, data); + var response = await _client.PostAsync(requestUrl, data); if (!response.IsSuccessStatusCode) { diff --git a/CandidateReviewClientApp/Controllers/AssessmentController.cs b/CandidateReviewClientApp/Controllers/AssessmentController.cs index 379c30b..d25eb8c 100644 --- a/CandidateReviewClientApp/Controllers/AssessmentController.cs +++ b/CandidateReviewClientApp/Controllers/AssessmentController.cs @@ -19,10 +19,8 @@ namespace CandidateReviewClientApp.Controllers _logger = logger; } - - [HttpPost] - public async Task AddAssessmentCriterion(int resumeId, int[] criterion, int[] value, string comment) + public async Task AddAssessmentCriterion(int resumeId, int[] criterion, int[] newValue, string comment) { string returnUrl = HttpContext.Request.Headers.Referer.ToString(); @@ -33,33 +31,35 @@ namespace CandidateReviewClientApp.Controllers throw new Exception("Необходима авторизация"); } - if (criterion == null || value == null || criterion.Length != value.Length) + if (criterion == null || newValue == null || criterion.Length != newValue.Length) { - throw new ArgumentException("Массивы критериев и оценок должны быть не null и одинаковой длины."); + throw new ArgumentException("Критерии или оценки заполнены некорректно."); } - Dictionary assCriterions = new(); - var userId = APIClient.User?.Id; var assessmentModel = new AssessmentBindingModel { ResumeId = resumeId, UserId = userId, - Comment = comment, - AssessmentCriterions = assCriterions + Comment = comment }; int assessmentId = await APIClient.PostRequestAsync("api/assessment/create", assessmentModel); - + List> criterionsValues = new(); for (int i = 0; i < criterion.Length; i++) { - var crit = APIClient.GetRequest($"api/criterion/details?id={criterion[i]}"); - assCriterions.Add(assessmentId, (new CriterionModel { Id = crit.Id, Name = crit.Name }, value[i])); + criterionsValues.Add(Tuple.Create(criterion[i], newValue[i])); + } + foreach (var item in criterionsValues) + { + var assessmentCriterion = new AssessmentCriterionModel + { + AssessmentId = assessmentId, + CriterionId = item.Item1, + Value = item.Item2 + }; + APIClient.PostRequest("api/assessment/createCriterion", assessmentCriterion); } - - assessmentModel.AssessmentCriterions = assCriterions; - assessmentModel.Id = assessmentId; - APIClient.PostRequest("api/assessment/update", assessmentModel); var user = APIClient.GetRequest($"api/user/profile?id={APIClient.User?.Id}"); @@ -67,8 +67,7 @@ namespace CandidateReviewClientApp.Controllers { ResumeId = assessmentModel.ResumeId, UserId = assessmentModel.UserId, - Comment = assessmentModel.Comment, - AssessmentCriterions = assessmentModel.AssessmentCriterions + Comment = assessmentModel.Comment }); var resume = APIClient.GetRequest($"api/resume/details?id={resumeId}"); if (resume != null) @@ -77,8 +76,7 @@ namespace CandidateReviewClientApp.Controllers { ResumeId = assessmentModel.ResumeId, UserId = assessmentModel.UserId, - Comment = assessmentModel.Comment, - AssessmentCriterions = assessmentModel.AssessmentCriterions + Comment = assessmentModel.Comment }); } else diff --git a/CandidateReviewClientApp/Controllers/ResumeController.cs b/CandidateReviewClientApp/Controllers/ResumeController.cs index d955349..df88bed 100644 --- a/CandidateReviewClientApp/Controllers/ResumeController.cs +++ b/CandidateReviewClientApp/Controllers/ResumeController.cs @@ -33,6 +33,23 @@ namespace CandidateReviewClientApp.Controllers var userAssessment = resumeAssessments?.FirstOrDefault(a => a.UserId == APIClient.User.Id); var criterions = APIClient.GetRequest>($"api/criterion/list"); resume.Assessments = resumeAssessments ?? new List(); + + var assessmentCriterions = new List(); + if (resumeAssessments != null) + { + foreach (var item in resumeAssessments) + { + assessmentCriterions.AddRange(APIClient.GetRequest>($"api/assessment/assessmentCriterions?assessmentId={item.Id}")); + } + } + + var userAC = new List(); + if (userAssessment != null) + { + userAC.AddRange(APIClient.GetRequest>($"api/assessment/assessmentCriterions?assessmentId={userAssessment.Id}")); + } + ViewBag.UserAssessmentCriterions = userAC; + ViewBag.OtherAssessmentCriterions = assessmentCriterions; ViewBag.UserAssessment = userAssessment; ViewBag.Criterions = criterions; diff --git a/CandidateReviewClientApp/Views/Resume/ResumeDetails.cshtml b/CandidateReviewClientApp/Views/Resume/ResumeDetails.cshtml index 2d4f95a..8949585 100644 --- a/CandidateReviewClientApp/Views/Resume/ResumeDetails.cshtml +++ b/CandidateReviewClientApp/Views/Resume/ResumeDetails.cshtml @@ -79,25 +79,27 @@ { foreach (var assessment in Model.Assessments) { - // Если это пользовательская оценка, пропускаем её, так как она будет отображена отдельно. if (ViewBag.UserAssessment is AssessmentViewModel currentUserAssessment && assessment.UserId == currentUserAssessment.UserId) { continue; }

Оценка пользователя: @assessment.UserName

- @foreach (var criterion in assessment.AssessmentCriterions) + @if (ViewBag.OtherAssessmentCriterions is List otherCriterions) { -
-
- + @foreach (var assessmentCriterion in otherCriterions.Where(ac => ac.AssessmentId == assessment.Id)) + { +
+
+ +
+
+ +
-
- -
-
+ } }

Комментарий: @assessment.Comment

} @@ -112,22 +114,25 @@ {

Ваша оценка

- @foreach (var criterion in userAssessment.AssessmentCriterions) + @if (ViewBag.UserAssessmentCriterions is List myCriterions) { -
-
- + @foreach (var assessmentCriterion in myCriterions) + { +
+
+ +
+
+ +
-
- -
-
+ } }

Комментарий: @userAssessment.Comment

- - Удалить оценку @@ -150,7 +155,7 @@
- +
@@ -197,7 +202,7 @@
- +
diff --git a/CandidateReviewContracts/BindingModels/AssessmentBindingModel.cs b/CandidateReviewContracts/BindingModels/AssessmentBindingModel.cs index 86d81f0..6d1f3ab 100644 --- a/CandidateReviewContracts/BindingModels/AssessmentBindingModel.cs +++ b/CandidateReviewContracts/BindingModels/AssessmentBindingModel.cs @@ -10,7 +10,7 @@ namespace CandidateReviewContracts.BindingModels public string? Comment { get; set; } public int Id { get; set; } - public Dictionary AssessmentCriterions { get; set; } = new(); + //public Dictionary AssessmentCriterions { get; set; } = new(); public int? ResumeId { get; set; } } diff --git a/CandidateReviewContracts/BindingModels/AssessmentCriterionModel.cs b/CandidateReviewContracts/BindingModels/AssessmentCriterionModel.cs new file mode 100644 index 0000000..348afd7 --- /dev/null +++ b/CandidateReviewContracts/BindingModels/AssessmentCriterionModel.cs @@ -0,0 +1,15 @@ +using CandidateReviewDataModels.Models; + +namespace CandidateReviewContracts.BindingModels +{ + public class AssessmentCriterionModel : IAssessmentCriterionModel + { + public int AssessmentId { get; set; } + + public int CriterionId { get; set; } + + public int Value { get; set; } + + public int Id { get; set; } + } +} diff --git a/CandidateReviewContracts/BusinessLogicsContracts/IAssessmentCriterionLogic.cs b/CandidateReviewContracts/BusinessLogicsContracts/IAssessmentCriterionLogic.cs new file mode 100644 index 0000000..b2bf88f --- /dev/null +++ b/CandidateReviewContracts/BusinessLogicsContracts/IAssessmentCriterionLogic.cs @@ -0,0 +1,15 @@ +using CandidateReviewContracts.BindingModels; +using CandidateReviewContracts.SearchModels; +using CandidateReviewContracts.ViewModels; + +namespace CandidateReviewContracts.BusinessLogicsContracts +{ + public interface IAssessmentCriterionLogic + { + List? ReadList(AssessmentCriterionSearchModel? model); + AssessmentCriterionViewModel? ReadElement(AssessmentCriterionSearchModel model); + bool Create(AssessmentCriterionModel model); + bool Update(AssessmentCriterionModel model); + bool Delete(AssessmentCriterionModel model); + } +} diff --git a/CandidateReviewContracts/SearchModels/AssessmentCriterionSearchModel.cs b/CandidateReviewContracts/SearchModels/AssessmentCriterionSearchModel.cs new file mode 100644 index 0000000..cc8eca1 --- /dev/null +++ b/CandidateReviewContracts/SearchModels/AssessmentCriterionSearchModel.cs @@ -0,0 +1,10 @@ +namespace CandidateReviewContracts.SearchModels +{ + public class AssessmentCriterionSearchModel + { + public int? Id { get; set; } + public int? AssessmentId { get; set; } + public int? CriterionId { get; set; } + public int? Value { get; set; } + } +} diff --git a/CandidateReviewContracts/StoragesContracts/IAssessmentCriterionStorage.cs b/CandidateReviewContracts/StoragesContracts/IAssessmentCriterionStorage.cs new file mode 100644 index 0000000..25f3167 --- /dev/null +++ b/CandidateReviewContracts/StoragesContracts/IAssessmentCriterionStorage.cs @@ -0,0 +1,18 @@ +using CandidateReviewContracts.BindingModels; +using CandidateReviewContracts.SearchModels; +using CandidateReviewContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CandidateReviewContracts.StoragesContracts +{ + public interface IAssessmentCriterionStorage + { + AssessmentCriterionViewModel? Insert(AssessmentCriterionModel model); + List GetFullList(); + List GetFilteredList(AssessmentCriterionSearchModel model); + } +} diff --git a/CandidateReviewContracts/ViewModels/AssessmentCriterionViewModel.cs b/CandidateReviewContracts/ViewModels/AssessmentCriterionViewModel.cs new file mode 100644 index 0000000..76ad759 --- /dev/null +++ b/CandidateReviewContracts/ViewModels/AssessmentCriterionViewModel.cs @@ -0,0 +1,17 @@ +using CandidateReviewDataModels.Models; + +namespace CandidateReviewContracts.ViewModels +{ + public class AssessmentCriterionViewModel : IAssessmentCriterionModel + { + public int AssessmentId { get; set; } + + public int CriterionId { get; set; } + + public string CriterionName { get; set; } = string.Empty; + + public int Value { get; set; } + + public int Id { get; set; } + } +} diff --git a/CandidateReviewContracts/ViewModels/AssessmentViewModel.cs b/CandidateReviewContracts/ViewModels/AssessmentViewModel.cs index f4759d9..154b728 100644 --- a/CandidateReviewContracts/ViewModels/AssessmentViewModel.cs +++ b/CandidateReviewContracts/ViewModels/AssessmentViewModel.cs @@ -13,7 +13,5 @@ namespace CandidateReviewContracts.ViewModels public int Id { get; set; } public int? ResumeId { get; set; } - - public Dictionary AssessmentCriterions { get; set; } = new(); } } diff --git a/CandidateReviewDataModels/Models/CriterionModel.cs b/CandidateReviewDataModels/Models/CriterionModel.cs deleted file mode 100644 index 7308547..0000000 --- a/CandidateReviewDataModels/Models/CriterionModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CandidateReviewDataModels.Models -{ - public class CriterionModel : ICriterionModel - { - public string Name { get; set; } = string.Empty; - - public int Id { get; set; } - } -} diff --git a/CandidateReviewDataModels/Models/IAssessmentCriterionModel.cs b/CandidateReviewDataModels/Models/IAssessmentCriterionModel.cs new file mode 100644 index 0000000..61d3dce --- /dev/null +++ b/CandidateReviewDataModels/Models/IAssessmentCriterionModel.cs @@ -0,0 +1,9 @@ +namespace CandidateReviewDataModels.Models +{ + public interface IAssessmentCriterionModel : IId + { + int AssessmentId { get; } + int CriterionId { get; } + int Value { get; } + } +} diff --git a/CandidateReviewDatabaseImplement/Implements/AssessmentCriterionStorage.cs b/CandidateReviewDatabaseImplement/Implements/AssessmentCriterionStorage.cs new file mode 100644 index 0000000..a603641 --- /dev/null +++ b/CandidateReviewDatabaseImplement/Implements/AssessmentCriterionStorage.cs @@ -0,0 +1,52 @@ +using CandidateReviewContracts.BindingModels; +using CandidateReviewContracts.SearchModels; +using CandidateReviewContracts.StoragesContracts; +using CandidateReviewContracts.ViewModels; +using CandidateReviewDatabaseImplement.Models; + +namespace CandidateReviewDatabaseImplement.Implements +{ + public class AssessmentCriterionStorage : IAssessmentCriterionStorage + { + public AssessmentCriterionViewModel? Insert(AssessmentCriterionModel model) + { + var newAssessmentCriterion = AssessmentCriterion.Create(model); + if (newAssessmentCriterion == null) + { + return null; + } + using var context = new CandidateReviewDatabase(); + context.AssessmentCriterions.Add(newAssessmentCriterion); + context.SaveChanges(); + return newAssessmentCriterion.GetViewModel; + } + + public List GetFullList() + { + using var context = new CandidateReviewDatabase(); + return context.AssessmentCriterions + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(AssessmentCriterionSearchModel model) + { + + using var context = new CandidateReviewDatabase(); + if (model.AssessmentId.HasValue) + { + return context.AssessmentCriterions + .Where(x => x.AssessmentId == model.AssessmentId) + .Select(x => x.GetViewModel) + .ToList(); + } + if (!model.Id.HasValue) + { + return new(); + } + return context.AssessmentCriterions + .Where(x => x.Id == model.Id) + .Select(x => x.GetViewModel) + .ToList(); + } + } +} diff --git a/CandidateReviewDatabaseImplement/Implements/AssessmentStorage.cs b/CandidateReviewDatabaseImplement/Implements/AssessmentStorage.cs index e2d98ea..ca84f54 100644 --- a/CandidateReviewDatabaseImplement/Implements/AssessmentStorage.cs +++ b/CandidateReviewDatabaseImplement/Implements/AssessmentStorage.cs @@ -15,15 +15,20 @@ namespace CandidateReviewDatabaseImplement.Implements using var context = new CandidateReviewDatabase(); var element = context.Assessments - .Include(x => x.Criterions) - .ThenInclude(x => x.Criterion) - .Include(x => x.User) - .Include(x => x.Resume) + .Include(x => x.User) + .Include(x => x.Resume) .FirstOrDefault(rec => rec.Id == model.Id); if (element != null) { + var relatedCriterions = context.AssessmentCriterions + .Where(x => x.AssessmentId == element.Id) + .ToList(); + + context.AssessmentCriterions.RemoveRange(relatedCriterions); + context.Assessments.Remove(element); + context.SaveChanges(); return element.GetViewModel; @@ -99,8 +104,6 @@ namespace CandidateReviewDatabaseImplement.Implements return context.Assessments .Include(x => x.User) .Include(x => x.Resume) - .Include(x => x.Criterions) - .ThenInclude(x => x.Criterion) .Select(x => x.GetViewModel).ToList(); } @@ -123,25 +126,14 @@ namespace CandidateReviewDatabaseImplement.Implements public AssessmentViewModel? Update(AssessmentBindingModel model) { using var context = new CandidateReviewDatabase(); - using var transaction = context.Database.BeginTransaction(); - try + var assessment = context.Assessments.FirstOrDefault(x => x.Id == model.Id); + if (assessment == null) { - var assessment = context.Assessments.FirstOrDefault(rec => rec.Id == model.Id); - if (assessment == null) - { - return null; - } - assessment.Update(model); - context.SaveChanges(); - assessment.UpdateCriterions(context, model); - transaction.Commit(); - return assessment.GetViewModel; - } - catch - { - transaction.Rollback(); - throw; + return null; } + assessment.Update(model); + context.SaveChanges(); + return assessment.GetViewModel; } } } diff --git a/CandidateReviewDatabaseImplement/Migrations/20241203082827_InitialCreate.Designer.cs b/CandidateReviewDatabaseImplement/Migrations/20241213205048_InitialCreate.Designer.cs similarity index 89% rename from CandidateReviewDatabaseImplement/Migrations/20241203082827_InitialCreate.Designer.cs rename to CandidateReviewDatabaseImplement/Migrations/20241213205048_InitialCreate.Designer.cs index f6d1ebe..b979bb3 100644 --- a/CandidateReviewDatabaseImplement/Migrations/20241203082827_InitialCreate.Designer.cs +++ b/CandidateReviewDatabaseImplement/Migrations/20241213205048_InitialCreate.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace CandidateReviewDatabaseImplement.Migrations { [DbContext(typeof(CandidateReviewDatabase))] - [Migration("20241203082827_InitialCreate")] + [Migration("20241213205048_InitialCreate")] partial class InitialCreate { /// @@ -70,10 +70,6 @@ namespace CandidateReviewDatabaseImplement.Migrations b.HasKey("Id"); - b.HasIndex("AssessmentId"); - - b.HasIndex("CriterionId"); - b.ToTable("AssessmentCriterions"); }); @@ -286,25 +282,6 @@ namespace CandidateReviewDatabaseImplement.Migrations b.Navigation("User"); }); - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.AssessmentCriterion", b => - { - b.HasOne("CandidateReviewDatabaseImplement.Models.Assessment", "Assessment") - .WithMany("Criterions") - .HasForeignKey("AssessmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("CandidateReviewDatabaseImplement.Models.Criterion", "Criterion") - .WithMany("AssessmentCriterions") - .HasForeignKey("CriterionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Assessment"); - - b.Navigation("Criterion"); - }); - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.Resume", b => { b.HasOne("CandidateReviewDatabaseImplement.Models.User", "User") @@ -343,16 +320,6 @@ namespace CandidateReviewDatabaseImplement.Migrations b.Navigation("Company"); }); - - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.Assessment", b => - { - b.Navigation("Criterions"); - }); - - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.Criterion", b => - { - b.Navigation("AssessmentCriterions"); - }); #pragma warning restore 612, 618 } } diff --git a/CandidateReviewDatabaseImplement/Migrations/20241203082827_InitialCreate.cs b/CandidateReviewDatabaseImplement/Migrations/20241213205048_InitialCreate.cs similarity index 91% rename from CandidateReviewDatabaseImplement/Migrations/20241203082827_InitialCreate.cs rename to CandidateReviewDatabaseImplement/Migrations/20241213205048_InitialCreate.cs index 08851e3..4193793 100644 --- a/CandidateReviewDatabaseImplement/Migrations/20241203082827_InitialCreate.cs +++ b/CandidateReviewDatabaseImplement/Migrations/20241213205048_InitialCreate.cs @@ -12,6 +12,21 @@ namespace CandidateReviewDatabaseImplement.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "AssessmentCriterions", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + AssessmentId = table.Column(type: "integer", nullable: false), + CriterionId = table.Column(type: "integer", nullable: false), + Value = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AssessmentCriterions", x => x.Id); + }); + migrationBuilder.CreateTable( name: "Companies", columns: table => new @@ -156,43 +171,6 @@ namespace CandidateReviewDatabaseImplement.Migrations principalColumn: "Id"); }); - migrationBuilder.CreateTable( - name: "AssessmentCriterions", - columns: table => new - { - Id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - AssessmentId = table.Column(type: "integer", nullable: false), - CriterionId = table.Column(type: "integer", nullable: false), - Value = table.Column(type: "integer", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AssessmentCriterions", x => x.Id); - table.ForeignKey( - name: "FK_AssessmentCriterions_Assessments_AssessmentId", - column: x => x.AssessmentId, - principalTable: "Assessments", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AssessmentCriterions_Criterions_CriterionId", - column: x => x.CriterionId, - principalTable: "Criterions", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AssessmentCriterions_AssessmentId", - table: "AssessmentCriterions", - column: "AssessmentId"); - - migrationBuilder.CreateIndex( - name: "IX_AssessmentCriterions_CriterionId", - table: "AssessmentCriterions", - column: "CriterionId"); - migrationBuilder.CreateIndex( name: "IX_Assessments_ResumeId", table: "Assessments", diff --git a/CandidateReviewDatabaseImplement/Migrations/CandidateReviewDatabaseModelSnapshot.cs b/CandidateReviewDatabaseImplement/Migrations/CandidateReviewDatabaseModelSnapshot.cs index 4c1e3bb..301089f 100644 --- a/CandidateReviewDatabaseImplement/Migrations/CandidateReviewDatabaseModelSnapshot.cs +++ b/CandidateReviewDatabaseImplement/Migrations/CandidateReviewDatabaseModelSnapshot.cs @@ -67,10 +67,6 @@ namespace CandidateReviewDatabaseImplement.Migrations b.HasKey("Id"); - b.HasIndex("AssessmentId"); - - b.HasIndex("CriterionId"); - b.ToTable("AssessmentCriterions"); }); @@ -283,25 +279,6 @@ namespace CandidateReviewDatabaseImplement.Migrations b.Navigation("User"); }); - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.AssessmentCriterion", b => - { - b.HasOne("CandidateReviewDatabaseImplement.Models.Assessment", "Assessment") - .WithMany("Criterions") - .HasForeignKey("AssessmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("CandidateReviewDatabaseImplement.Models.Criterion", "Criterion") - .WithMany("AssessmentCriterions") - .HasForeignKey("CriterionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Assessment"); - - b.Navigation("Criterion"); - }); - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.Resume", b => { b.HasOne("CandidateReviewDatabaseImplement.Models.User", "User") @@ -340,16 +317,6 @@ namespace CandidateReviewDatabaseImplement.Migrations b.Navigation("Company"); }); - - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.Assessment", b => - { - b.Navigation("Criterions"); - }); - - modelBuilder.Entity("CandidateReviewDatabaseImplement.Models.Criterion", b => - { - b.Navigation("AssessmentCriterions"); - }); #pragma warning restore 612, 618 } } diff --git a/CandidateReviewDatabaseImplement/Models/Assessment.cs b/CandidateReviewDatabaseImplement/Models/Assessment.cs index 430703e..4314e42 100644 --- a/CandidateReviewDatabaseImplement/Models/Assessment.cs +++ b/CandidateReviewDatabaseImplement/Models/Assessment.cs @@ -1,8 +1,6 @@ using CandidateReviewContracts.BindingModels; using CandidateReviewContracts.ViewModels; using CandidateReviewDataModels.Models; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; namespace CandidateReviewDatabaseImplement.Models { @@ -18,25 +16,6 @@ namespace CandidateReviewDatabaseImplement.Models public virtual User User { get; set; } public virtual Resume Resume { get; set; } - private Dictionary? _assessmentCriterions = null; - - public Dictionary AssessmentCriterions - { - get - { - if (_assessmentCriterions == null) - { - _assessmentCriterions = Criterions - .ToDictionary(recAC => recAC.CriterionId, recAC => - (new CriterionModel { Id = recAC.Criterion.Id, Name = recAC.Criterion.Name }, recAC.Value)); - } - return _assessmentCriterions; - } - } - - [ForeignKey("AssessmentId")] - public virtual List Criterions { get; set; } = new(); - public static Assessment Create(CandidateReviewDatabase context, AssessmentBindingModel model) { return new Assessment() @@ -44,12 +23,7 @@ namespace CandidateReviewDatabaseImplement.Models Id = model.Id, ResumeId = model.ResumeId, UserId = model.UserId, - Comment = model.Comment, - Criterions = model.AssessmentCriterions.Select(x => new AssessmentCriterion - { - Assessment = context.Assessments.First(y => y.Id == x.Key), - Value = x.Value.Item2 - }).ToList() + Comment = model.Comment }; } @@ -64,48 +38,12 @@ namespace CandidateReviewDatabaseImplement.Models Comment = model.Comment; } - public AssessmentViewModel GetViewModel => new() { Id = Id, ResumeId = ResumeId, UserId = UserId, - Comment = Comment, - AssessmentCriterions = AssessmentCriterions + Comment = Comment }; - - public void UpdateCriterions(CandidateReviewDatabase context, AssessmentBindingModel model) - { - var assessmentCriterions = context.AssessmentCriterions.Where(rec => rec.AssessmentId == model.Id).ToList(); - if (assessmentCriterions != null && assessmentCriterions.Count > 0) - { - context.AssessmentCriterions.RemoveRange(assessmentCriterions.Where(rec => !model.AssessmentCriterions.ContainsKey(rec.CriterionId))); - context.SaveChanges(); - foreach (var updateCriterion in assessmentCriterions) - { - updateCriterion.Value = model.AssessmentCriterions[updateCriterion.CriterionId].Item2; - model.AssessmentCriterions.Remove(updateCriterion.CriterionId); - } - context.SaveChanges(); - } - var assessment = context.Assessments.First(x => x.Id == Id); - foreach (var ac in model.AssessmentCriterions) - { - var criterion = context.Criterions.First(x => x.Id == ac.Value.Item1.Id); - if (criterion == null) - { - throw new Exception($"Критерий с ID {ac.Key} не найден."); - } - - context.AssessmentCriterions.Add(new AssessmentCriterion - { - Assessment = assessment, - Criterion = criterion, - Value = ac.Value.Item2 - }); - } - context.SaveChanges(); - _assessmentCriterions = null; - } } } diff --git a/CandidateReviewDatabaseImplement/Models/AssessmentCriterion.cs b/CandidateReviewDatabaseImplement/Models/AssessmentCriterion.cs index 05de3ee..d0b2bde 100644 --- a/CandidateReviewDatabaseImplement/Models/AssessmentCriterion.cs +++ b/CandidateReviewDatabaseImplement/Models/AssessmentCriterion.cs @@ -1,5 +1,7 @@ -using CandidateReviewContracts.ViewModels; +using CandidateReviewContracts.BindingModels; +using CandidateReviewContracts.ViewModels; using System.ComponentModel.DataAnnotations; +using System.Net; namespace CandidateReviewDatabaseImplement.Models { @@ -12,7 +14,28 @@ namespace CandidateReviewDatabaseImplement.Models public int CriterionId { get; set; } [Required] public int Value { get; set; } - public virtual Assessment Assessment { get; set; } = new(); - public virtual Criterion Criterion { get; set; } = new(); + + public static AssessmentCriterion? Create(AssessmentCriterionModel model) + { + if (model == null) + { + return null; + } + return new AssessmentCriterion() + { + Id = model.Id, + AssessmentId = model.AssessmentId, + CriterionId = model.CriterionId, + Value = model.Value + }; + } + + public AssessmentCriterionViewModel GetViewModel => new() + { + Id = Id, + AssessmentId = AssessmentId, + CriterionId = CriterionId, + Value = Value + }; } } diff --git a/CandidateReviewDatabaseImplement/Models/Criterion.cs b/CandidateReviewDatabaseImplement/Models/Criterion.cs index 01f978d..d0ed1b5 100644 --- a/CandidateReviewDatabaseImplement/Models/Criterion.cs +++ b/CandidateReviewDatabaseImplement/Models/Criterion.cs @@ -12,8 +12,6 @@ namespace CandidateReviewDatabaseImplement.Models public string Name { get; set; } = string.Empty; public int Id { get; set; } - [ForeignKey("CriterionId")] - public virtual List AssessmentCriterions { get; set; } = new(); public static Criterion? Create(CriterionBindingModel model) { diff --git a/CandidateReviewRestApi/Controllers/AssessmentController.cs b/CandidateReviewRestApi/Controllers/AssessmentController.cs index e28666f..3a12191 100644 --- a/CandidateReviewRestApi/Controllers/AssessmentController.cs +++ b/CandidateReviewRestApi/Controllers/AssessmentController.cs @@ -13,10 +13,12 @@ namespace CandidateReviewRestApi.Controllers { private readonly ILogger _logger; private readonly IAssessmentLogic _logic; - public AssessmentController(IAssessmentLogic logic, ILogger logger) + private readonly IAssessmentCriterionLogic _logicAC; + public AssessmentController(IAssessmentLogic logic, ILogger logger, IAssessmentCriterionLogic logicAC) { _logger = logger; _logic = logic; + _logicAC = logicAC; } [HttpGet] @@ -53,6 +55,23 @@ namespace CandidateReviewRestApi.Controllers } } + [HttpGet] + public List? AssessmentCriterions(int assessmentId) + { + try + { + return _logicAC.ReadList(new AssessmentCriterionSearchModel + { + AssessmentId = assessmentId + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения оценок"); + throw; + } + } + [HttpPost] public IActionResult Create(AssessmentBindingModel model) { @@ -68,6 +87,20 @@ namespace CandidateReviewRestApi.Controllers } } + [HttpPost] + public void CreateCriterion(AssessmentCriterionModel model) + { + try + { + _logicAC.Create(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка создания оценки"); + throw; + } + } + [HttpPost] public void Update(AssessmentBindingModel model) { diff --git a/CandidateReviewRestApi/Program.cs b/CandidateReviewRestApi/Program.cs index bb65aa2..74aa185 100644 --- a/CandidateReviewRestApi/Program.cs +++ b/CandidateReviewRestApi/Program.cs @@ -17,6 +17,7 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); @@ -24,6 +25,7 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle