380 lines
18 KiB
C#
380 lines
18 KiB
C#
using CoreModels.Enums.Department;
|
||
using DepartmentBusinessLogic.HelperModels;
|
||
using DepartmentContract.BindingModels;
|
||
using DepartmentContract.Logics.IGenericEntityLogic;
|
||
using DepartmentContract.Services.IGenericEntityService;
|
||
using DepartmentContract.ViewModels;
|
||
using SecurityContract.BindingModels;
|
||
using SecurityContract.Logics.IGenericEntityLogic;
|
||
using SecurityContract.ViewModels;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Net.Http;
|
||
using System.Net.Http.Headers;
|
||
using System.Text;
|
||
using System.Text.Json;
|
||
using System.Threading.Tasks;
|
||
using ToolsModule.ManagmentDependency;
|
||
using ToolsModule.ManagmentEntity;
|
||
using ToolsModule.ManagmentExtension;
|
||
using ToolsModule.ManagmentMapping;
|
||
using ToolsModule.ManagmentSecurity;
|
||
|
||
namespace DepartmentBusinessLogic.BusinessLogics.GenericBusinessLogic
|
||
{
|
||
/// <summary>
|
||
/// Логика работы с историями синхронизации оценок
|
||
/// </summary>
|
||
public class StudentMarkSyncHistoryBusinessLogic : GenericBusinessLogic<StudentMarkSyncHistoryGetBindingModel, StudentMarkSyncHistorySetBindingModel, StudentMarkSyncHistoryListViewModel, StudentMarkSyncHistoryViewModel>, IStudentMarkSyncHistoryLogic
|
||
{
|
||
private IStudentMarkSyncHistoryRecordLogic _recordLogic;
|
||
|
||
private IEnviromentSettingLogic _enviromentSettingLogic;
|
||
|
||
private IStudentLogic _studentLogic;
|
||
|
||
private IDisciplineLogic _disciplineLogic;
|
||
|
||
private ILecturerLogic _lecturerLogic;
|
||
|
||
private IStudentMarkPassedDisciplineLogic _studentMarkPassedDisciplineLogic;
|
||
|
||
private StudentMarkSyncHistoryViewModel _history;
|
||
|
||
public StudentMarkSyncHistoryBusinessLogic(IStudentMarkSyncHistoryService service) : base(service, "Синхронизация Оценок", AccessOperation.ОценкиСтудентов) { }
|
||
|
||
public async Task<bool> SyncMarks()
|
||
{
|
||
InitLogics();
|
||
|
||
// создание логов по операции синхронизации приказов
|
||
if (!CreateHistory())
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// получение адреса сервера с приказами
|
||
var address = GetAddress();
|
||
if (address == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// подключение клиента для отправки запросов к серверу
|
||
var client = GetClinet(address);
|
||
if (client == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// получение списка оценок
|
||
var response = await client.GetAsync($"{address.Value}/univer/hs/Ulstu_StudentsInfo/v1/GetCurrentStudentsOfDepartmentGrades");
|
||
if (!response.IsSuccessStatusCode)
|
||
{
|
||
SaveLog("Не удалось получить список оценок студента с сервера");
|
||
return false;
|
||
}
|
||
var studentFromServer = JsonSerializer.Deserialize<StudentInfoListForMarkSyncModel>(await response.Content.ReadAsStringAsync());
|
||
if (studentFromServer == null || studentFromServer.arrayOfStudentsGrades == null)
|
||
{
|
||
SaveLog("Не удалось распознать список приказов по студенту");
|
||
return false;
|
||
}
|
||
if (studentFromServer.arrayOfStudentsGrades.Length == 0)
|
||
{
|
||
SaveLog("Полученный список студентов пустой");
|
||
return false;
|
||
}
|
||
|
||
var students = _studentLogic.GetList(new StudentGetBindingModel());
|
||
if (students == null || students.List == null)
|
||
{
|
||
SaveErrors(_studentLogic.Errors, "Ошибка получения данных", "Не удалось получить список студентов с базы");
|
||
return false;
|
||
}
|
||
foreach (var student in students.List)
|
||
{
|
||
var marks = studentFromServer.arrayOfStudentsGrades.FirstOrDefault(x => x.recordBook == student.NumberOfBook);
|
||
if (marks == null || marks.bills == null || marks.bills.Length == 0)
|
||
{
|
||
SaveLog($"По студенту {student} ({student.NumberOfBook}) не найдено оценок");
|
||
continue;
|
||
}
|
||
SyncMarks(student, marks.bills);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Инициализаия всех логик для получения от них данных и сохранения новых
|
||
/// </summary>
|
||
private void InitLogics()
|
||
{
|
||
_recordLogic = DependencyManager.Instance.Resolve<IStudentMarkSyncHistoryRecordLogic>();
|
||
_enviromentSettingLogic = DependencyManager.Instance.Resolve<IEnviromentSettingLogic>();
|
||
_studentLogic = DependencyManager.Instance.Resolve<IStudentLogic>();
|
||
_disciplineLogic = DependencyManager.Instance.Resolve<IDisciplineLogic>();
|
||
_lecturerLogic = DependencyManager.Instance.Resolve<ILecturerLogic>();
|
||
_studentMarkPassedDisciplineLogic = DependencyManager.Instance.Resolve<IStudentMarkPassedDisciplineLogic>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создаение логера действий при синхронизации приказов
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private bool CreateHistory()
|
||
{
|
||
_history = Create(new StudentMarkSyncHistorySetBindingModel { SyncDate = DateTime.Now });
|
||
if (_history == null)
|
||
{
|
||
Errors.Add(("Ошибка создание истории", "Не удалось создать историю"));
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Получение адреса сервера
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private EnviromentSettingViewModel GetAddress()
|
||
{
|
||
var address = _enviromentSettingLogic.GetList(new EnviromentSettingGetBindingModel { Key = "SyncStudentOrderIpAddress" })?.List?.FirstOrDefault();
|
||
if (address == null || address.Value.IsEmpty())
|
||
{
|
||
SaveErrors(_enviromentSettingLogic.Errors, "Ошибка получения данных", "Не удалось получить адрес сервера для получения приказов по студентам");
|
||
return null;
|
||
}
|
||
return address;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Получение клиента для работы с сервисом приказов
|
||
/// </summary>
|
||
/// <param name="address"></param>
|
||
/// <returns></returns>
|
||
private HttpClient GetClinet(EnviromentSettingViewModel address)
|
||
{
|
||
var username = _enviromentSettingLogic.GetList(new EnviromentSettingGetBindingModel { Key = "SyncStudentOrderUserName" })?.List?.FirstOrDefault();
|
||
if (username == null || username.Value.IsEmpty())
|
||
{
|
||
SaveErrors(_enviromentSettingLogic.Errors, "Ошибка получения данных", "Не удалось получить имя пользователя для получения приказов по студентам");
|
||
return null;
|
||
}
|
||
|
||
var password = _enviromentSettingLogic.GetList(new EnviromentSettingGetBindingModel { Key = "SyncStudentOrderPassword" })?.List?.FirstOrDefault();
|
||
if (password == null || password.Value.IsEmpty())
|
||
{
|
||
SaveErrors(_enviromentSettingLogic.Errors, "Ошибка получения данных", "Не удалось получить пароль для получения приказов по студентам");
|
||
return null;
|
||
}
|
||
|
||
var client = new HttpClient
|
||
{
|
||
BaseAddress = new Uri(address.Value),
|
||
Timeout = TimeSpan.FromMinutes(10)
|
||
};
|
||
client.DefaultRequestHeaders.Accept.Clear();
|
||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username.Value}:{password.Value}")));
|
||
|
||
return client;
|
||
}
|
||
|
||
private void SyncMarks(StudentViewModel student, StudentMarkSyncModel[] bills)
|
||
{
|
||
var marks = _studentMarkPassedDisciplineLogic.GetList(new StudentMarkPassedDisciplineGetBindingModel { StudentId = student.Id });
|
||
if (marks == null || marks.List == null)
|
||
{
|
||
SaveErrors(_studentLogic.Errors, "Ошибка получения данных", $"Не удалось получить список оценок студента {student} с базы");
|
||
return;
|
||
}
|
||
var studentBills = bills.ToList();
|
||
foreach (var bill in bills)
|
||
{
|
||
var disciplines = _disciplineLogic.GetList(new DisciplineGetBindingModel { DisciplineName = bill.disciplineName });
|
||
if (disciplines == null || disciplines.List == null || disciplines.List.Count == 0)
|
||
{
|
||
SaveLog($"Не найдена дисциплина {bill.disciplineName}");
|
||
continue;
|
||
}
|
||
var discipline = disciplines.List.First();
|
||
var sb = new StringBuilder();
|
||
LecturerViewModel lecturer = null;
|
||
|
||
var teachers = bill.teacher.Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||
foreach (var retacher in teachers)
|
||
{
|
||
var lecturers = _lecturerLogic.GetList(new LecturerGetBindingModel { FIO = bill.teacher });
|
||
if (lecturers != null && lecturers.List != null && lecturers.List.Count > 0)
|
||
{
|
||
lecturer = lecturers.List.First();
|
||
break;
|
||
}
|
||
}
|
||
if (lecturer == null)
|
||
{
|
||
sb.Append($"Преподаватель: {bill.teacher} ");
|
||
}
|
||
var semester = GetSemester(bill);
|
||
if (semester == Semester.Нулевой)
|
||
{
|
||
sb.Append($"Семестр: {bill.semester} ");
|
||
}
|
||
var type = GetDisicplineReportingType(bill);
|
||
if (type == DisciplineReportingType.Неопределено)
|
||
{
|
||
sb.Append($"Тип: {bill.controlType} ");
|
||
}
|
||
var mark = GetMark(bill);
|
||
if (mark == MarkDisciplinePassedType.НеСдано)
|
||
{
|
||
sb.Append($"Оценка: {bill.grade} ");
|
||
}
|
||
var date = Convert.ToDateTime(bill.controlTypeDate);
|
||
var isDirection = bill.documentType != "Аттестационная ведомость";
|
||
var markFound = marks.List.FirstOrDefault(x => x.DisciplineId == discipline.Id && x.StudentId == student.Id &&
|
||
x.Semester == semester && x.DisciplineReportingType == type && x.DateAffixing.Date == date.Date);
|
||
if (markFound != null)
|
||
{
|
||
if (markFound.Mark != mark || markFound.IsDirection != isDirection || markFound.LecturerId != lecturer?.Id)
|
||
{
|
||
markFound.Mark = mark;
|
||
markFound.IsDirection = isDirection;
|
||
markFound.LecturerId = lecturer?.Id;
|
||
markFound = _studentMarkPassedDisciplineLogic.Update(Mapper.MapToClass<StudentMarkPassedDisciplineViewModel, StudentMarkPassedDisciplineSetBindingModel>(markFound, true));
|
||
if (markFound == null)
|
||
{
|
||
SaveErrors(_studentMarkPassedDisciplineLogic.Errors, "Ошибка изменения данных", $"Не удалось обновить оценку студента {student}");
|
||
}
|
||
else
|
||
{
|
||
SaveLog($"Оценка обновлена: {student}, {bill.disciplineName}, {semester}, {type}, {mark}, {lecturer?.ToString()}");
|
||
}
|
||
}
|
||
if (markFound != null)
|
||
{
|
||
marks.List.RemoveAll(x => x.Id == markFound.Id);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var newMark = _studentMarkPassedDisciplineLogic.Create(new StudentMarkPassedDisciplineSetBindingModel
|
||
{
|
||
DisciplineId = discipline.Id,
|
||
StudentId = student.Id,
|
||
Semester = semester,
|
||
DisciplineReportingType = type,
|
||
Mark = mark,
|
||
DateAffixing = date,
|
||
IsDirection = isDirection,
|
||
LecturerId = lecturer?.Id,
|
||
AddiionalInfo = sb.ToString()
|
||
});
|
||
if (newMark == null)
|
||
{
|
||
SaveErrors(_studentMarkPassedDisciplineLogic.Errors, "Ошибка добавления данных", $"Не удалось добавить оценку студента {student}");
|
||
}
|
||
else
|
||
{
|
||
SaveLog($"Оценка добавлена: {student}, {bill.disciplineName}, {semester}, {type}, {mark}, {lecturer?.ToString()}");
|
||
}
|
||
}
|
||
}
|
||
if (marks.List.Count > 0)
|
||
{
|
||
foreach (var mark in marks.List)
|
||
{
|
||
SaveLog($"Попытка удаления оценки: {student}, {mark}");
|
||
if (!_studentMarkPassedDisciplineLogic.Delete(new StudentMarkPassedDisciplineGetBindingModel { Id = mark.Id }))
|
||
{
|
||
SaveErrors(_studentMarkPassedDisciplineLogic.Errors, "Ошибка удаления данных", $"Не удалось удалить оценку студента {student}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Получение семестра
|
||
/// </summary>
|
||
/// <param name="bill"></param>
|
||
/// <returns></returns>
|
||
private static Semester GetSemester(StudentMarkSyncModel bill) => Convert.ToInt32(bill.semester) switch
|
||
{
|
||
1 => Semester.Первый,
|
||
2 => Semester.Второй,
|
||
3 => Semester.Третий,
|
||
4 => Semester.Четвертый,
|
||
5 => Semester.Пятый,
|
||
6 => Semester.Шестой,
|
||
7 => Semester.Седьмой,
|
||
8 => Semester.Восьмой,
|
||
9 => Semester.Девятый,
|
||
10 => Semester.Десятый,
|
||
_ => Semester.Нулевой,
|
||
};
|
||
|
||
/// <summary>
|
||
/// Получение типа отчетности: зачет, экзамен..
|
||
/// </summary>
|
||
/// <param name="bill"></param>
|
||
/// <returns></returns>
|
||
private static DisciplineReportingType GetDisicplineReportingType(StudentMarkSyncModel bill) => bill.controlType switch
|
||
{
|
||
"Зачет" => DisciplineReportingType.Зачет,
|
||
"Дифференцированный зачет" => DisciplineReportingType.ЗачетСОценкой,
|
||
"Курсовая работа" => DisciplineReportingType.КурсоваяРабота,
|
||
"Курсовой проект" => DisciplineReportingType.КурсовойПроект,
|
||
"Экзамен" => DisciplineReportingType.Экзамен,
|
||
_ => DisciplineReportingType.Неопределено,
|
||
};
|
||
|
||
/// <summary>
|
||
/// Определение результата сдачи зачета/экзамена
|
||
/// </summary>
|
||
/// <param name="bill"></param>
|
||
/// <returns></returns>
|
||
private static MarkDisciplinePassedType GetMark(StudentMarkSyncModel bill) => bill.grade switch
|
||
{
|
||
"Неявка" => MarkDisciplinePassedType.НеЯвился,
|
||
"Зачтено" => MarkDisciplinePassedType.Зачет,
|
||
"Неудовлетворительно" => MarkDisciplinePassedType.НеУдовлетворительно,
|
||
"Удовлетворительно" => MarkDisciplinePassedType.Удовлетворительно,
|
||
"Хорошо" => MarkDisciplinePassedType.Хорошо,
|
||
"Отлично" => MarkDisciplinePassedType.Отлично,
|
||
_ => MarkDisciplinePassedType.НеСдано,
|
||
};
|
||
|
||
/// <summary>
|
||
/// Сохранение лога с ошибками
|
||
/// </summary>
|
||
/// <param name="errors"></param>
|
||
/// <param name="title"></param>
|
||
/// <param name="message"></param>
|
||
private void SaveErrors(List<(string Title, string Message)> errors, string title, string message)
|
||
{
|
||
if (_history == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
Errors = errors ?? new List<(string Title, string Message)>();
|
||
Errors.Add((title, message));
|
||
SaveLog(string.Join(Environment.NewLine, Errors.Select(x => x.Message)));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Сохранение лога
|
||
/// </summary>
|
||
/// <param name="info"></param>
|
||
private void SaveLog(string info)
|
||
{
|
||
_recordLogic.Create(new StudentMarkSyncHistoryRecordSetBindingModel
|
||
{
|
||
StudentMarkSyncHistoryId = _history.Id,
|
||
Information = info
|
||
});
|
||
}
|
||
}
|
||
} |