оценка резюме не доделана
This commit is contained in:
parent
e18de8db1d
commit
aa28aecfc1
@ -3,6 +3,7 @@ using CandidateReviewContracts.BusinessLogicsContracts;
|
||||
using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.StoragesContracts;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@ -17,17 +18,52 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
_logger = logger;
|
||||
_assessmentStorage = assessmentStorage;
|
||||
}
|
||||
public bool Create(AssessmentBindingModel model)
|
||||
|
||||
public bool AddCriterionToAssessment(AssessmentSearchModel model, ICriterionModel criterion, int value)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_assessmentStorage.Insert(model) == null)
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (criterion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(criterion));
|
||||
}
|
||||
|
||||
var element = _assessmentStorage.GetElement(model);
|
||||
|
||||
if (element == null)
|
||||
{
|
||||
_logger.LogWarning("Insert operation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
element.AssessmentCriterions[element.Id] = (criterion, value);
|
||||
|
||||
_assessmentStorage.Update(new AssessmentBindingModel
|
||||
{
|
||||
Id = element.Id,
|
||||
UserId = element.UserId,
|
||||
ResumeId = element.ResumeId,
|
||||
Comment = element.Comment,
|
||||
AssessmentCriterions = element.AssessmentCriterions
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int? Create(AssessmentBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
var id = _assessmentStorage.Insert(model);
|
||||
if (id == null)
|
||||
{
|
||||
_logger.LogWarning("Insert operation failed");
|
||||
return 0;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public bool Delete(AssessmentBindingModel model)
|
||||
{
|
||||
CheckModel(model, false);
|
||||
|
@ -45,22 +45,6 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
return true;
|
||||
}
|
||||
|
||||
/*public CompanyViewModel? ReadElement(CompanySearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
var element = _сompanyStorage.GetElement(model);
|
||||
if (element == null)
|
||||
{
|
||||
_logger.LogWarning("ReadElement element not found");
|
||||
return null;
|
||||
}
|
||||
_logger.LogInformation("ReadElement find. Id: {Id}", element.Id);
|
||||
return element;
|
||||
}*/
|
||||
|
||||
public CompanyViewModel? ReadElement(CompanySearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
|
@ -82,7 +82,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
Description = element.Description,
|
||||
Skills = element.Skills,
|
||||
Status = element.Status,
|
||||
PreviousAssessments = assessmentViewModels
|
||||
Assessments = assessmentViewModels
|
||||
};
|
||||
_logger.LogInformation("ReadElement find. Id: {Id}", element.Id);
|
||||
return resumeViewModel;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using CandidateReviewClientApp.Models;
|
||||
using CandidateReviewContracts.BindingModels;
|
||||
using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -17,48 +18,53 @@ namespace CandidateReviewClientApp.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult AddAssessment(int resumeId, string comment, Dictionary<int, int> criteriaValues)
|
||||
public async Task<IActionResult> AddAssessmentCriterion(int resumeId, int[] criterion, int[] value, string comment)
|
||||
{
|
||||
string returnUrl = HttpContext.Request.Headers["Referer"].ToString();
|
||||
|
||||
try
|
||||
{
|
||||
var userId = APIClient.User?.Id;
|
||||
var allCriterions = APIClient.GetRequest<List<CriterionViewModel>>("api/criterion/list");
|
||||
if (allCriterions == null || !allCriterions.Any())
|
||||
if (APIClient.User == null)
|
||||
{
|
||||
throw new Exception("Критерии не найдены");
|
||||
throw new Exception("Необходима авторизация");
|
||||
}
|
||||
|
||||
criteriaValues = criteriaValues.Where(kvp => kvp.Key != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
if (criterion == null || value == null || criterion.Length != value.Length)
|
||||
{
|
||||
throw new ArgumentException("Массивы критериев и оценок должны быть не null и одинаковой длины.");
|
||||
}
|
||||
|
||||
var assessmentCriterions = criteriaValues
|
||||
.ToDictionary(
|
||||
kvp => kvp.Key,
|
||||
kvp =>
|
||||
{
|
||||
var criterionViewModel = allCriterions.FirstOrDefault(c => c.Id == kvp.Key);
|
||||
if (criterionViewModel == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Критерий с ID {kvp.Key} не найден.");
|
||||
}
|
||||
var userId = APIClient.User?.Id;
|
||||
var assessmentData = new Dictionary<int, (ICriterionModel, int)>();
|
||||
|
||||
var criterionModel = new CriterionViewModel
|
||||
{
|
||||
Id = criterionViewModel.Id,
|
||||
Name = criterionViewModel.Name
|
||||
};
|
||||
|
||||
return ((ICriterionModel)criterionModel, kvp.Value);
|
||||
}
|
||||
);
|
||||
|
||||
APIClient.PostRequest("api/assessment/create", new AssessmentBindingModel
|
||||
var assessmentModel = new AssessmentBindingModel
|
||||
{
|
||||
ResumeId = resumeId,
|
||||
UserId = userId,
|
||||
Comment = comment,
|
||||
AssessmentCriterions = assessmentCriterions
|
||||
});
|
||||
AssessmentCriterions = new Dictionary<int, (ICriterionModel, int)>()
|
||||
};
|
||||
|
||||
var assessmentId = await APIClient.PostRequestAsync("api/assessment/create", assessmentModel);
|
||||
|
||||
for (int i = 0; i < criterion.Length; i++)
|
||||
{
|
||||
if (value[i] < 1 || value[i] > 5)
|
||||
{
|
||||
throw new ArgumentException($"Оценка для критерия {criterion[i]} должна быть от 1 до 5.");
|
||||
}
|
||||
|
||||
if (assessmentData.ContainsKey(assessmentId))
|
||||
{
|
||||
assessmentData[assessmentId] = (new CriterionViewModel { Id = criterion[i] }, value[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
assessmentData.Add(assessmentId, (new CriterionViewModel { Id = criterion[i] }, value[i]));
|
||||
}
|
||||
}
|
||||
|
||||
APIClient.PostRequest("api/assessment/AddCriterionToAssessment", assessmentData);
|
||||
|
||||
return Redirect($"~/Resume/ResumeDetails/{resumeId}");
|
||||
}
|
||||
|
@ -28,12 +28,12 @@ namespace CandidateReviewClientApp.Controllers
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
var assessments = APIClient.GetRequest<List<AssessmentViewModel>>($"api/assessment/listByResumeId?id={id}");
|
||||
var criterions = APIClient.GetRequest<List<CriterionViewModel>>($"api/criterion/list");
|
||||
|
||||
resume.Assessments = assessments;
|
||||
ViewBag.Criterions = criterions;
|
||||
return View(resume);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> EditResume(int? id, int? vacancyId)
|
||||
|
@ -63,35 +63,28 @@
|
||||
{
|
||||
<h2 class="mb-4">Оценка резюме</h2>
|
||||
|
||||
<form method="post" asp-controller="Assessment" asp-action="AddAssessment">
|
||||
<div class="row" id="criteriaList">
|
||||
@if (ViewBag.Criterions != null)
|
||||
{
|
||||
<input type="hidden" name="ResumeId" value="@Model?.Id" />
|
||||
@foreach (var criterion in ViewBag.Criterions)
|
||||
{
|
||||
var previousAssessment = Model.PreviousAssessments?.FirstOrDefault(a => a.Id == criterion.Id);
|
||||
var isSelected = previousAssessment?.Id == criterion.Id ? "selected" : string.Empty;
|
||||
<form method="post" asp-controller="Assessment" asp-action="AddAssessmentCriterion">
|
||||
<input type="hidden" name="ResumeId" value="@Model.Id" />
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<select name="criterionIds[]" class="form-control" required>
|
||||
<option value="" disabled selected>Выберите критерий</option>
|
||||
<option value="@criterion.Id" isSelected>@criterion.Name</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="criteriaValues[]" min="1" max="5"
|
||||
value="@previousAssessment?.AssessmentCriterions?.FirstOrDefault().Value" required />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
@if (ViewBag.Criterions != null)
|
||||
{
|
||||
foreach (var criterion in ViewBag.Criterions)
|
||||
{
|
||||
<p>Нет доступных критериев.</p>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" value="@criterion.Name" readonly />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="value[]" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
<input type="hidden" name="criterion[]" value="@criterion.Id" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Нет доступных критериев.</p>
|
||||
}
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
@ -100,8 +93,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-primary mt-3" id="addCriterionBtn">Оценить по другому критерию</button>
|
||||
|
||||
<button type="submit" class="btn btn-success mt-3">Сохранить</button>
|
||||
</form>
|
||||
|
||||
@ -114,53 +105,5 @@
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var criterions = @Html.Raw(Json.Serialize(ViewBag.Criterions));
|
||||
|
||||
document.getElementById('addCriterionBtn').addEventListener('click', function () {
|
||||
var criteriaList = document.getElementById('criteriaList');
|
||||
var newRow = document.createElement('div');
|
||||
newRow.classList.add('row', 'mb-3');
|
||||
|
||||
// Создаем выпадающий список для критерия
|
||||
var criterionSelect = document.createElement('div');
|
||||
criterionSelect.classList.add('col-md-6');
|
||||
var select = document.createElement('select');
|
||||
select.classList.add('form-control');
|
||||
select.name = 'criterionIds[]';
|
||||
select.required = true;
|
||||
|
||||
var defaultOption = document.createElement('option');
|
||||
defaultOption.value = "";
|
||||
defaultOption.textContent = "Выберите критерий";
|
||||
select.appendChild(defaultOption);
|
||||
|
||||
criterions.forEach(function (criterion) {
|
||||
var option = document.createElement('option');
|
||||
option.value = criterion.id;
|
||||
option.textContent = criterion.name;
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
criterionSelect.appendChild(select);
|
||||
|
||||
// Создаем поле ввода для оценки
|
||||
var valueInput = document.createElement('div');
|
||||
valueInput.classList.add('col-md-6');
|
||||
var input = document.createElement('input');
|
||||
input.type = 'number';
|
||||
input.classList.add('form-control');
|
||||
input.name = 'criteriaValues[]';
|
||||
input.min = 1;
|
||||
input.max = 5;
|
||||
input.required = true; // Обязательное поле
|
||||
|
||||
valueInput.appendChild(input);
|
||||
|
||||
// Добавляем созданные элементы в новый ряд
|
||||
newRow.appendChild(criterionSelect);
|
||||
newRow.appendChild(valueInput);
|
||||
|
||||
// Добавляем новый ряд в список критериев
|
||||
criteriaList.appendChild(newRow);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using CandidateReviewContracts.BindingModels;
|
||||
using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
|
||||
namespace CandidateReviewContracts.BusinessLogicsContracts
|
||||
{
|
||||
@ -8,7 +9,8 @@ namespace CandidateReviewContracts.BusinessLogicsContracts
|
||||
{
|
||||
List<AssessmentViewModel>? ReadList(AssessmentSearchModel? model);
|
||||
AssessmentViewModel? ReadElement(AssessmentSearchModel model);
|
||||
bool Create(AssessmentBindingModel model);
|
||||
int? Create(AssessmentBindingModel model);
|
||||
bool AddCriterionToAssessment(AssessmentSearchModel model, ICriterionModel criterion, int value);
|
||||
bool Update(AssessmentBindingModel model);
|
||||
bool Delete(AssessmentBindingModel model);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace CandidateReviewContracts.StoragesContracts
|
||||
List<AssessmentViewModel> GetFullList();
|
||||
List<AssessmentViewModel> GetFilteredList(AssessmentSearchModel model);
|
||||
AssessmentViewModel? GetElement(AssessmentSearchModel model);
|
||||
AssessmentViewModel? Insert(AssessmentBindingModel model);
|
||||
int? Insert(AssessmentBindingModel model);
|
||||
AssessmentViewModel? Update(AssessmentBindingModel model);
|
||||
AssessmentViewModel? Delete(AssessmentBindingModel model);
|
||||
}
|
||||
|
@ -28,6 +28,6 @@ namespace CandidateReviewContracts.ViewModels
|
||||
public ResumeStatusEnum Status { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
public List<AssessmentViewModel> PreviousAssessments { get; set; } = new();
|
||||
public List<AssessmentViewModel> Assessments { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
.Select(x => x.GetViewModel).ToList();
|
||||
}
|
||||
|
||||
public AssessmentViewModel? Insert(AssessmentBindingModel model)
|
||||
public int? Insert(AssessmentBindingModel model)
|
||||
{
|
||||
using var context = new CandidateReviewDatabase();
|
||||
var newAssessment = Assessment.Create(context, model);
|
||||
@ -112,7 +112,7 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
context.Assessments.Add(newAssessment);
|
||||
context.SaveChanges();
|
||||
|
||||
return newAssessment.GetViewModel;
|
||||
return newAssessment.Id;
|
||||
}
|
||||
|
||||
public AssessmentViewModel? Update(AssessmentBindingModel model)
|
||||
|
@ -25,15 +25,22 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
|
||||
public UserViewModel? GetElement(UserSearchModel model)
|
||||
{
|
||||
if (string.IsNullOrEmpty(model.Email) && !model.Id.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using var context = new CandidateReviewDatabase();
|
||||
return context.Users
|
||||
if (!string.IsNullOrEmpty(model.Email))
|
||||
{
|
||||
return context.Users
|
||||
.Include(x => x.Company)
|
||||
.FirstOrDefault(x => (!string.IsNullOrEmpty(model.Email) && x.Email == model.Email) || (model.Id.HasValue && x.Id == model.Id))?
|
||||
.FirstOrDefault(x => (!string.IsNullOrEmpty(model.Email) && x.Email == model.Email))?
|
||||
.GetViewModel;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return context.Users
|
||||
.Include(x => x.Company)
|
||||
.FirstOrDefault(x => (x.Id == model.Id))?
|
||||
.GetViewModel;
|
||||
}
|
||||
}
|
||||
|
||||
public List<UserViewModel> GetFilteredList(UserSearchModel model)
|
||||
|
@ -2,6 +2,7 @@
|
||||
using CandidateReviewContracts.BusinessLogicsContracts;
|
||||
using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace CandidateReviewRestApi.Controllers
|
||||
@ -35,12 +36,47 @@ namespace CandidateReviewRestApi.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void Create(AssessmentBindingModel model)
|
||||
[HttpGet]
|
||||
public List<AssessmentViewModel>? ListByUserId(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logic.Create(model);
|
||||
return _logic.ReadList(new AssessmentSearchModel
|
||||
{
|
||||
UserId = id
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка получения оценок");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public List<AssessmentViewModel>? ListByResumeId(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _logic.ReadList(new AssessmentSearchModel
|
||||
{
|
||||
ResumeId = id
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка получения оценок");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public int? Create(AssessmentBindingModel model)
|
||||
{
|
||||
try
|
||||
{
|
||||
int? id = _logic.Create(model);
|
||||
return id;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -48,6 +84,53 @@ namespace CandidateReviewRestApi.Controllers
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost]
|
||||
public void AddCriterionToAssessment(Dictionary<int, (ICriterionModel, int)> model)
|
||||
{
|
||||
if (model == null || model.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("Модель данных не должна быть пустой.", nameof(model));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var kvp in model)
|
||||
{
|
||||
var id = kvp.Key;
|
||||
var (criterion, value) = kvp.Value;
|
||||
|
||||
if (criterion == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!model.ContainsKey(id))
|
||||
{
|
||||
model.Add(id, (criterion, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
model[id] = (criterion, value);
|
||||
}
|
||||
|
||||
var success = _logic.AddCriterionToAssessment(
|
||||
new AssessmentSearchModel { Id = id },
|
||||
criterion,
|
||||
value
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw new Exception("Ошибка добавления критерия.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка добавления критериев.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void Update(AssessmentBindingModel model)
|
||||
|
Loading…
Reference in New Issue
Block a user