оценка по критерию есть, удаление корректно, отображение корректно + мелкие правки
This commit is contained in:
parent
fd31ade855
commit
a954a4d741
@ -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<AssessmentLogic> 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<AssessmentCriterionViewModel>? ReadList(AssessmentCriterionSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _assessmentCriterionStorage.GetFullList() : _assessmentCriterionStorage.GetFilteredList(model);
|
||||
|
||||
if (list == null)
|
||||
{
|
||||
_logger.LogWarning("ReadList return null list");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<AssessmentCriterionViewModel> 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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<AssessmentLogic> logger, IAssessmentStorage assessmentStorage, IUserStorage userStorage, ICriterionStorage criterionStorage)
|
||||
public AssessmentLogic(ILogger<AssessmentLogic> 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<AssessmentViewModel> 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)
|
||||
|
@ -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<AssessmentViewModel>();
|
||||
|
||||
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<AssessmentViewModel>();
|
||||
|
||||
var resumeViewModel = new ResumeViewModel
|
||||
|
@ -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<T>(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)
|
||||
{
|
||||
|
@ -19,10 +19,8 @@ namespace CandidateReviewClientApp.Controllers
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddAssessmentCriterion(int resumeId, int[] criterion, int[] value, string comment)
|
||||
public async Task<IActionResult> 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<int, (CriterionModel, int)> 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<Tuple<int, int>> criterionsValues = new();
|
||||
for (int i = 0; i < criterion.Length; i++)
|
||||
{
|
||||
var crit = APIClient.GetRequest<CriterionViewModel>($"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<UserViewModel>($"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<ResumeViewModel>($"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
|
||||
|
@ -33,6 +33,23 @@ namespace CandidateReviewClientApp.Controllers
|
||||
var userAssessment = resumeAssessments?.FirstOrDefault(a => a.UserId == APIClient.User.Id);
|
||||
var criterions = APIClient.GetRequest<List<CriterionViewModel>>($"api/criterion/list");
|
||||
resume.Assessments = resumeAssessments ?? new List<AssessmentViewModel>();
|
||||
|
||||
var assessmentCriterions = new List<AssessmentCriterionViewModel>();
|
||||
if (resumeAssessments != null)
|
||||
{
|
||||
foreach (var item in resumeAssessments)
|
||||
{
|
||||
assessmentCriterions.AddRange(APIClient.GetRequest<List<AssessmentCriterionViewModel>>($"api/assessment/assessmentCriterions?assessmentId={item.Id}"));
|
||||
}
|
||||
}
|
||||
|
||||
var userAC = new List<AssessmentCriterionViewModel>();
|
||||
if (userAssessment != null)
|
||||
{
|
||||
userAC.AddRange(APIClient.GetRequest<List<AssessmentCriterionViewModel>>($"api/assessment/assessmentCriterions?assessmentId={userAssessment.Id}"));
|
||||
}
|
||||
ViewBag.UserAssessmentCriterions = userAC;
|
||||
ViewBag.OtherAssessmentCriterions = assessmentCriterions;
|
||||
ViewBag.UserAssessment = userAssessment;
|
||||
ViewBag.Criterions = criterions;
|
||||
|
||||
|
@ -79,25 +79,27 @@
|
||||
{
|
||||
foreach (var assessment in Model.Assessments)
|
||||
{
|
||||
// Если это пользовательская оценка, пропускаем её, так как она будет отображена отдельно.
|
||||
if (ViewBag.UserAssessment is AssessmentViewModel currentUserAssessment && assessment.UserId == currentUserAssessment.UserId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
<h4>Оценка пользователя: @assessment.UserName</h4>
|
||||
@foreach (var criterion in assessment.AssessmentCriterions)
|
||||
@if (ViewBag.OtherAssessmentCriterions is List<AssessmentCriterionViewModel> otherCriterions)
|
||||
{
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control" disabled>
|
||||
<option value="@criterion.Value.Item1.Id" selected>@criterion.Value.Item1.Name</option>
|
||||
</select>
|
||||
@foreach (var assessmentCriterion in otherCriterions.Where(ac => ac.AssessmentId == assessment.Id))
|
||||
{
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control" disabled>
|
||||
<option value="@assessmentCriterion.CriterionId" selected>@assessmentCriterion.CriterionName</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@assessmentCriterion.Value" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value.Item2" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<p>Комментарий: @assessment.Comment</p>
|
||||
}
|
||||
@ -112,22 +114,25 @@
|
||||
{
|
||||
<div id="user-assessment-container">
|
||||
<h4>Ваша оценка</h4>
|
||||
@foreach (var criterion in userAssessment.AssessmentCriterions)
|
||||
@if (ViewBag.UserAssessmentCriterions is List<AssessmentCriterionViewModel> myCriterions)
|
||||
{
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control" disabled>
|
||||
<option value="@criterion.Value.Item1.Id" selected>@criterion.Value.Item1.Name</option>
|
||||
</select>
|
||||
@foreach (var assessmentCriterion in myCriterions)
|
||||
{
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control" disabled>
|
||||
<option value="@assessmentCriterion.CriterionId" selected>@assessmentCriterion.CriterionName</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@assessmentCriterion.Value" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value.Item2" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<p>Комментарий: @userAssessment.Comment</p>
|
||||
|
||||
<a asp-controller="Assessment" asp-action="Delete" asp-route-id="@userAssessment.Id" asp-route-resumeId="@Model.Id" onclick="return confirm('Вы уверены, что хотите удалить оценку?');"
|
||||
<a asp-controller="Assessment" asp-action="Delete" asp-route-id="@userAssessment.Id" asp-route-resumeId="@Model.Id"
|
||||
onclick="return confirm('Вы уверены, что хотите удалить оценку?');"
|
||||
class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
Удалить оценку
|
||||
</a>
|
||||
@ -150,7 +155,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="value" class="form-control" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
<input type="number" name="newValue" class="form-control" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
</div>
|
||||
<div class="col-md-1 d-flex align-items-center">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-criterion">Х</button>
|
||||
@ -197,7 +202,7 @@
|
||||
<select name="criterion" class="form-control">${selectOptions}</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="value" class="form-control" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
<input type="number" name="newValue" class="form-control" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
</div>
|
||||
<div class="col-md-1 d-flex align-items-center">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-criterion">✕</button>
|
||||
|
@ -10,7 +10,7 @@ namespace CandidateReviewContracts.BindingModels
|
||||
public string? Comment { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
public Dictionary<int, (CriterionModel, int)> AssessmentCriterions { get; set; } = new();
|
||||
//public Dictionary<int, (int, int)> AssessmentCriterions { get; set; } = new();
|
||||
|
||||
public int? ResumeId { get; set; }
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using CandidateReviewContracts.BindingModels;
|
||||
using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
|
||||
namespace CandidateReviewContracts.BusinessLogicsContracts
|
||||
{
|
||||
public interface IAssessmentCriterionLogic
|
||||
{
|
||||
List<AssessmentCriterionViewModel>? ReadList(AssessmentCriterionSearchModel? model);
|
||||
AssessmentCriterionViewModel? ReadElement(AssessmentCriterionSearchModel model);
|
||||
bool Create(AssessmentCriterionModel model);
|
||||
bool Update(AssessmentCriterionModel model);
|
||||
bool Delete(AssessmentCriterionModel model);
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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<AssessmentCriterionViewModel> GetFullList();
|
||||
List<AssessmentCriterionViewModel> GetFilteredList(AssessmentCriterionSearchModel model);
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -13,7 +13,5 @@ namespace CandidateReviewContracts.ViewModels
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? ResumeId { get; set; }
|
||||
|
||||
public Dictionary<int, (CriterionModel, int)> AssessmentCriterions { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
namespace CandidateReviewDataModels.Models
|
||||
{
|
||||
public interface IAssessmentCriterionModel : IId
|
||||
{
|
||||
int AssessmentId { get; }
|
||||
int CriterionId { get; }
|
||||
int Value { get; }
|
||||
}
|
||||
}
|
@ -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<AssessmentCriterionViewModel> GetFullList()
|
||||
{
|
||||
using var context = new CandidateReviewDatabase();
|
||||
return context.AssessmentCriterions
|
||||
.Select(x => x.GetViewModel)
|
||||
.ToList();
|
||||
}
|
||||
public List<AssessmentCriterionViewModel> 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace CandidateReviewDatabaseImplement.Migrations
|
||||
{
|
||||
[DbContext(typeof(CandidateReviewDatabase))]
|
||||
[Migration("20241203082827_InitialCreate")]
|
||||
[Migration("20241213205048_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@ -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
|
||||
}
|
||||
}
|
@ -12,6 +12,21 @@ namespace CandidateReviewDatabaseImplement.Migrations
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AssessmentCriterions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
AssessmentId = table.Column<int>(type: "integer", nullable: false),
|
||||
CriterionId = table.Column<int>(type: "integer", nullable: false),
|
||||
Value = table.Column<int>(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<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
AssessmentId = table.Column<int>(type: "integer", nullable: false),
|
||||
CriterionId = table.Column<int>(type: "integer", nullable: false),
|
||||
Value = table.Column<int>(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",
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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<int, (CriterionModel, int)>? _assessmentCriterions = null;
|
||||
|
||||
public Dictionary<int, (CriterionModel, int)> 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<AssessmentCriterion> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,6 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public int Id { get; set; }
|
||||
[ForeignKey("CriterionId")]
|
||||
public virtual List<AssessmentCriterion> AssessmentCriterions { get; set; } = new();
|
||||
|
||||
public static Criterion? Create(CriterionBindingModel model)
|
||||
{
|
||||
|
@ -13,10 +13,12 @@ namespace CandidateReviewRestApi.Controllers
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IAssessmentLogic _logic;
|
||||
public AssessmentController(IAssessmentLogic logic, ILogger<AssessmentController> logger)
|
||||
private readonly IAssessmentCriterionLogic _logicAC;
|
||||
public AssessmentController(IAssessmentLogic logic, ILogger<AssessmentController> logger, IAssessmentCriterionLogic logicAC)
|
||||
{
|
||||
_logger = logger;
|
||||
_logic = logic;
|
||||
_logicAC = logicAC;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
@ -53,6 +55,23 @@ namespace CandidateReviewRestApi.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public List<AssessmentCriterionViewModel>? 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)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ builder.Services.AddTransient<IVacancyStorage, VacancyStorage>();
|
||||
builder.Services.AddTransient<IResumeStorage, ResumeStorage>();
|
||||
builder.Services.AddTransient<IAssessmentStorage, AssessmentStorage>();
|
||||
builder.Services.AddTransient<ICriterionStorage, CriterionStorage>();
|
||||
builder.Services.AddTransient<IAssessmentCriterionStorage, AssessmentCriterionStorage>();
|
||||
|
||||
builder.Services.AddTransient<IUserLogic, UserLogic>();
|
||||
builder.Services.AddTransient<ICompanyLogic, CompanyLogic>();
|
||||
@ -24,6 +25,7 @@ builder.Services.AddTransient<IVacancyLogic, VacancyLogic>();
|
||||
builder.Services.AddTransient<IResumeLogic, ResumeLogic>();
|
||||
builder.Services.AddTransient<IAssessmentLogic, AssessmentLogic>();
|
||||
builder.Services.AddTransient<ICriterionLogic, CriterionLogic>();
|
||||
builder.Services.AddTransient<IAssessmentCriterionLogic, AssessmentCriterionLogic>();
|
||||
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
|
Loading…
Reference in New Issue
Block a user