синхронизация студентов + восстановдение удаленной сущностий

This commit is contained in:
kotcheshir73 2021-04-28 17:58:52 +04:00
parent 68c01f1801
commit ba184943c4
8 changed files with 465 additions and 158 deletions

View File

@ -59,7 +59,7 @@ namespace DatabaseCore
using var transaction = context.Database.BeginTransaction();
try
{
var entity = context.Set<T>().FirstOrDefault(x => x.Id == model.Id);
var entity = await context.Set<T>().FirstOrDefaultAsync(x => x.Id == model.Id);
if (entity == null)
{
return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound);
@ -93,6 +93,30 @@ namespace DatabaseCore
return OperationResultModel.Success(true);
}
public async Task<OperationResultModel> RestoreAsync(G model)
{
if (model.Id.HasValue || AdditionalCheckForSingleGet(model))
{
using var context = DatabaseManager.GetContext;
var entity = model.Id.HasValue ? IncludingWhenReading(context.Set<T>().AsQueryable()).FirstOrDefault(x => x.Id == model.Id.Value)
: GetSingleRecord(context.Set<T>().AsQueryable(), model);
if (entity == null)
{
return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound);
}
else if (!entity.IsDeleted)
{
return OperationResultModel.Error("Error:", "Элемент не был удален", ResultServiceStatusCode.ExsistItem);
}
entity.IsDeleted = false;
await context.SaveChangesAsync();
return OperationResultModel.Success(Mapper.MapToClass<T, E>(entity, true));
}
return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound);
}
public async Task<OperationResultModel> ReadAsync(G model)
{
int countPages = 0;
@ -107,6 +131,10 @@ namespace DatabaseCore
{
return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound);
}
if (entity.IsDeleted)
{
return OperationResultModel.Error("Error:", "Элемент удален", ResultServiceStatusCode.WasDelete);
}
return OperationResultModel.Success(Mapper.MapToClass<T, E>(entity, model.HaveRight));
}

View File

@ -29,6 +29,11 @@ namespace DatabaseCore.Models.Department
[MapConfiguration("StudentGroupId")]
public Guid? StudentGroupId { get; set; }
[DataMember]
[Required]
[MapConfiguration("Iduniv")]
public string Iduniv { get; set; }
[DataMember]
[Required]
[MapConfiguration("NumberOfBook")]

View File

@ -187,5 +187,35 @@ namespace ModuleTools.BusinessLogics
}
return false;
}
/// <summary>
/// Восстанолвение записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<E> RestoreAsync(G model)
{
Errors.Clear();
try
{
if (NoAccess(model, AccessType.Change))
{
return null;
}
var result = await Service.RestoreAsync(model);
if (!result.IsSucceeded)
{
Errors.AddRange(result.Errors);
return null;
}
return result.Result as E;
}
catch (Exception ex)
{
Errors.Add(("Ошибка удаления", ex.Message));
}
return null;
}
}
}

View File

@ -38,5 +38,12 @@ namespace ModuleTools.Interfaces
/// <param name="model"></param>
/// <returns></returns>
Task<OperationResultModel> DeleteAsync(G model);
/// <summary>
/// Восстановление сущности
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
Task<OperationResultModel> RestoreAsync(G model);
}
}

View File

@ -16,6 +16,8 @@ namespace DepartmentBusinessLogic.BindingModels
public Guid? StudentGroupId { get; set; }
public StudentState? StudentState { get; set; }
public string NumberOfBook { get; set; }
}
/// <summary>
@ -30,6 +32,10 @@ namespace DepartmentBusinessLogic.BindingModels
[MapConfiguration("StudentGroupId")]
public Guid? StudentGroupId { get; set; }
[Required(ErrorMessage = "required")]
[MapConfiguration("Iduniv")]
public string Iduniv { get; set; }
[Required(ErrorMessage = "required")]
[MapConfiguration("NumberOfBook")]
public string NumberOfBook { get; set; }

View File

@ -161,19 +161,51 @@ namespace DepartmentBusinessLogic.BusinessLogics
// студент не найден, значит он ушел с кафедры, выясняем почему
if (studentSync == null)
{
await SyncStudentOrders(history, student, groups.List, client, address.Value, studentSync.iduniv);
await SyncStudentOrders(history, student, groups.List, client, address.Value);
}
// не совпадение групп
else if (student.StudentGroupName != studentSync.groupName)
{
await SyncStudentOrders(history, student, groups.List, client, address.Value, studentSync.iduniv);
await SyncStudentOrders(history, student, groups.List, client, address.Value);
}
studentFromServer.CurrentStudentsList.Remove(studentSync);
}
// новые студенты
// новые студенты и восстановленцы
foreach (var student in studentFromServer.CurrentStudentsList)
{
var deletedStudent = await _studentLogic.GetElementAsync(new StudentGetBindingModel { NumberOfBook = student.recordBookName });
if (deletedStudent == null && _studentLogic.Errors.FirstOrDefault(x => x.Message == "Элемент удален") != default)
{
// восстановленец
deletedStudent = await _studentLogic.RestoreAsync(new StudentGetBindingModel { NumberOfBook = student.recordBookName });
if (deletedStudent == null)
{
var errors = _studentLogic.Errors;
errors.Add(("Ошибка при восстановлении студента", $"Не удалось восстановить студента {student.lastName} {student.firstName} {student.patronymicName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
var deletedUser = await _userLogic.RestoreAsync(new UserGetBindingModel { Id = deletedStudent.UserId });
if (deletedUser == null)
{
var errors = _userLogic.Errors;
errors.Add(("Ошибка при восстановлении пользователя студента", $"Не удалось восстановить пользователя студента {student.lastName} {student.firstName} {student.patronymicName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
await SyncStudentOrders(history, deletedStudent, groups.List, client, address.Value);
continue;
}
var userName = $"{student.lastName}{(student.firstName.IsNotEmpty() ? $" {student.firstName[0]}." : string.Empty)}{(student.patronymicName.IsNotEmpty() ? $"{student.patronymicName[0]}." : string.Empty)}";
var result = await _userLogic.GetListAsync(new UserGetBindingModel { UserNameForSearch = userName });
@ -196,12 +228,13 @@ namespace DepartmentBusinessLogic.BusinessLogics
var newStudent = await _studentLogic.CreateAsync(new StudentSetBindingModel
{
Iduniv = student.iduniv,
NumberOfBook = student.recordBookName,
UserId = newuser.Id,
FirstName = student.firstName,
LastName = student.lastName,
Patronymic = student.patronymicName,
NumberOfBook = student.recordBookName,
StudentState = GetStudentState(student.stateName),
StudentState = StudentState.Неопределен,
Description = student.presenatationOfRecordBook
});
@ -223,7 +256,7 @@ namespace DepartmentBusinessLogic.BusinessLogics
Information = $"Добавлен студент {newStudent}"
});
await SyncStudentOrders(history, newStudent, groups.List, client, address.Value, student.iduniv);
await SyncStudentOrders(history, newStudent, groups.List, client, address.Value);
studentFromServer.CurrentStudentsList.Remove(student);
}
@ -231,13 +264,6 @@ namespace DepartmentBusinessLogic.BusinessLogics
return true;
}
private static StudentState GetStudentState(string state) => state switch
{
"Является студентом" => StudentState.Учится,
"Находится в академическом отпуске" => StudentState.Академ,
_ => StudentState.Неопределен,
};
/// <summary>
/// Синхронизация приказов по студенту
/// </summary>
@ -246,11 +272,10 @@ namespace DepartmentBusinessLogic.BusinessLogics
/// <param name="groups"></param>
/// <param name="client"></param>
/// <param name="address"></param>
/// <param name="iduniv"></param>
/// <returns></returns>
private async Task SyncStudentOrders(OrderSyncHistoryViewModel history, StudentViewModel student, List<StudentGroupViewModel> groups, HttpClient client, string address, string iduniv)
private async Task SyncStudentOrders(OrderSyncHistoryViewModel history, StudentViewModel student, List<StudentGroupViewModel> groups, HttpClient client, string address)
{
HttpResponseMessage response = await client.GetAsync($"{address}/univer_Testing/hs/Ulstu_StudentsInfo/v1/GetStudentOrdersByIdAndRecordBook?iduniv={iduniv}&recordBookName={student.NumberOfBook}&allOrders=sppd");
HttpResponseMessage response = await client.GetAsync($"{address}/univer_Testing/hs/Ulstu_StudentsInfo/v1/GetStudentOrdersByIdAndRecordBook?iduniv={student.Iduniv}&recordBookName={student.NumberOfBook}&allOrders=sppd");
if (!response.IsSuccessStatusCode)
{
Errors.Add(("Ошибка получения данных", "Не удалось получить список приказов по студенту"));
@ -265,9 +290,13 @@ namespace DepartmentBusinessLogic.BusinessLogics
foreach (var syncOrder in syncOrders.StudentOrders)
{
var orderType = GetOrderType(syncOrder.orderSubTypeName);
// отбираем только приказы, которые нас интересуют
if (orderType != OrderType.Неопределено)
// пропускаем приказы, которые нас не интересуют
if (orderType == OrderType.Неопределено)
{
continue;
}
// пытаемся найти приказ
var order = await _orderLogic.GetElementAsync(new OrderGetBindingModel
{
@ -302,8 +331,13 @@ namespace DepartmentBusinessLogic.BusinessLogics
OrderId = order.Id,
StudentId = student.Id
});
if (studentOrder == null)
// если такой приказ по студенту уже есть, просто пропускаем
if (studentOrder != null)
{
continue;
}
Guid? studentGroupFromId = null;
Guid? studentGroupToId = null;
string info = string.Empty;
@ -315,13 +349,23 @@ namespace DepartmentBusinessLogic.BusinessLogics
{
studentGroupToId = groups.FirstOrDefault(x => x.ToString() == syncOrder.groupNameAfter)?.Id;
}
// если был переведенец к нам, то игнорируем приказы, не связанные с нашими группами
if (!studentGroupFromId.HasValue && !studentGroupToId.HasValue)
{
continue;
}
OrderStudentMoveType orderStudentMoveType = OrderStudentMoveType.Неопределено;
switch (syncOrder.orderSubTypeName)
switch (syncOrder.orderTypeName)
{
case "Перевод":
if (syncOrder.orderSubTypeName == "Распределение по группам")
{
orderStudentMoveType = OrderStudentMoveType.Распределение;
info = $"Распределение студента {student} в группу {groups.First(x => x.Id == studentGroupToId)}";
}
// внутренний перевод
if (studentGroupFromId.HasValue && studentGroupToId.HasValue)
else if (studentGroupFromId.HasValue && studentGroupToId.HasValue)
{
orderStudentMoveType = OrderStudentMoveType.ПереводВГруппу;
info = $"Перевод студента {student} из группы {groups.First(x => x.Id == studentGroupFromId)} в группу {groups.First(x => x.Id == studentGroupToId)}";
@ -337,17 +381,45 @@ namespace DepartmentBusinessLogic.BusinessLogics
info = $"Отчисление студента {student} из группы {groups.First(x => x.Id == studentGroupFromId)} в связи с переводом";
}
break;
case "Зачисление в вуз":
case "Зачисление в вуз вне приемной кампании":
orderStudentMoveType = OrderStudentMoveType.Зачисление;
info = $"Зачисление студента {student}";
break;
case "Распределение по группам":
orderStudentMoveType = OrderStudentMoveType.Распределение;
info = $"Распределение студента {student} в группу {groups.First(x => x.Id == studentGroupToId)}";
break;
case "Перевод на следующий курс":
orderStudentMoveType = OrderStudentMoveType.ПереводНаКурс;
info = $"Перевод студента {student} на следующий курс";
info = $"Перевод студента {student} из группы {groups.First(x => x.Id == studentGroupFromId)} на следующий курс в группу {groups.First(x => x.Id == studentGroupToId)}";
break;
case "Уход в академический отпуск":
orderStudentMoveType = OrderStudentMoveType.ВАкадем;
info = $"Уход в АО студента {student} из группы {groups.First(x => x.Id == studentGroupFromId)}";
break;
case "Продление академического отпуска":
orderStudentMoveType = OrderStudentMoveType.ПродлАкадем;
info = $"Продление АО студента {student}";
break;
case "Восстановление из академического отпуска":
orderStudentMoveType = OrderStudentMoveType.ИзАкадема;
info = $"Выход из АО студента {student} в группу {groups.First(x => x.Id == studentGroupToId)}";
break;
case "Восстановление": // уточнить приказ
orderStudentMoveType = OrderStudentMoveType.Восстановить;
info = $"Восстановление отчисленного студента {student} в группу {groups.First(x => x.Id == studentGroupToId)}";
break;
case "Отчисление по собственному": // уточнить приказ
orderStudentMoveType = OrderStudentMoveType.ОтчислитьПоСобственному;
info = $"Отчисление студента {student} из группы {groups.First(x => x.Id == studentGroupFromId)} по собственному желанию";
break;
case "Отчисление за неуспеваемость": // уточнить приказ
orderStudentMoveType = OrderStudentMoveType.ОтчислитьПоСобственному;
info = $"Отчисление студента {student} из группы {groups.First(x => x.Id == studentGroupFromId)} за неуспеваемость";
break;
case "Отчисление по невыходу из академа": // уточнить приказ
orderStudentMoveType = OrderStudentMoveType.ОтчислитьПоСобственному;
info = $"Отчисление студента {student} по невыходу из академа";
break;
case "Хавершение обучения": // уточнить приказ
orderStudentMoveType = OrderStudentMoveType.ОтчислитьПоСобственному;
info = $"Отчисление студента {student} в связи с окончанием обучения";
break;
}
@ -378,11 +450,11 @@ namespace DepartmentBusinessLogic.BusinessLogics
continue;
}
var st = Mapper.MapToClass<StudentViewModel, StudentSetBindingModel>(student, true);
var studentName = student.ToString();
if (student.StudentGroupId != studentGroupToId)
{
var st = Mapper.MapToClass<StudentViewModel, StudentSetBindingModel>(student, true);
st.StudentGroupId = studentGroupToId;
var studentName = student.ToString();
student = await _studentLogic.UpdateAsync(st);
if (student == null)
{
@ -402,6 +474,144 @@ namespace DepartmentBusinessLogic.BusinessLogics
});
}
if ((orderStudentMoveType == OrderStudentMoveType.Зачисление || orderStudentMoveType == OrderStudentMoveType.ЗачислитьПоПереводу
|| orderStudentMoveType == OrderStudentMoveType.ПереводВГруппу) && student.StudentState != StudentState.Учится)
{
st.StudentState = StudentState.Учится;
student = await _studentLogic.UpdateAsync(st);
if (student == null)
{
var errors = _studentLogic.Errors;
errors.Add(("Ошибка изменения по студенту", $"Не удалось изменить статус у студента {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = $"У студента {student} сменился статус на {StudentState.Учится}"
});
}
if ((orderStudentMoveType == OrderStudentMoveType.ВАкадем || orderStudentMoveType == OrderStudentMoveType.ПродлАкадем)
&& student.StudentState != StudentState.Академ)
{
st.StudentState = StudentState.Академ;
student = await _studentLogic.UpdateAsync(st);
if (student == null)
{
var errors = _studentLogic.Errors;
errors.Add(("Ошибка изменения по студенту", $"Не удалось изменить статус у студента {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = $"У студента {student} сменился статус на {StudentState.Академ}"
});
}
if (orderStudentMoveType == OrderStudentMoveType.ИзАкадема && student.StudentState != StudentState.Учится)
{
st.StudentState = StudentState.Учится;
student = await _studentLogic.UpdateAsync(st);
if (student == null)
{
var errors = _studentLogic.Errors;
errors.Add(("Ошибка изменения по студенту", $"Не удалось изменить статус у студента {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = $"У студента {student} сменился статус на {StudentState.Учится}"
});
}
if ((orderStudentMoveType == OrderStudentMoveType.ОтчислитьВСвязиСПереводом || orderStudentMoveType == OrderStudentMoveType.ОтчислитьЗаНевыходСАкадема
|| orderStudentMoveType == OrderStudentMoveType.ОтчислитьЗаНеуспевамость || orderStudentMoveType == OrderStudentMoveType.ОтчислитьПоСобственному
|| orderStudentMoveType == OrderStudentMoveType.ОтчислитьПоЗавершению) && student.StudentState != StudentState.Отчислен)
{
st.StudentState = orderStudentMoveType == OrderStudentMoveType.ОтчислитьПоЗавершению ? StudentState.Завершил : StudentState.Отчислен;
student = await _studentLogic.UpdateAsync(st);
if (student == null)
{
var errors = _studentLogic.Errors;
errors.Add(("Ошибка изменения по студенту", $"Не удалось изменить статус у студента {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = $"У студента {student} сменился статус на {(orderStudentMoveType == OrderStudentMoveType.ОтчислитьПоЗавершению ? StudentState.Завершил : StudentState.Отчислен)}"
});
var result = await _studentLogic.DeleteAsync(new StudentGetBindingModel { Id = student.Id });
if (!result)
{
var errors = _userLogic.Errors;
errors.Add(("Ошибка удаления студента", $"Не удалось удалить студента {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
result = await _userLogic.DeleteAsync(new UserGetBindingModel { Id = student.UserId });
if (!result)
{
var errors = _userLogic.Errors;
errors.Add(("Ошибка удаления пользователя по студенту", $"Не удалось удалить пользователя по студенту {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
}
if (orderStudentMoveType == OrderStudentMoveType.Восстановить && student.StudentState != StudentState.Учится)
{
st.StudentState = StudentState.Учится;
student = await _studentLogic.UpdateAsync(st);
if (student == null)
{
var errors = _studentLogic.Errors;
errors.Add(("Ошибка изменения по студенту", $"Не удалось изменить статус у студента {studentName}"));
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = string.Join(Environment.NewLine, errors.Select(x => x.Message))
});
continue;
}
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
Information = $"У студента {student} сменился статус на {StudentState.Учится}"
});
}
await _recordLogic.CreateAsync(new OrderSyncHistoryRecordSetBindingModel
{
OrderSyncHistoryId = history.Id,
@ -418,8 +628,6 @@ namespace DepartmentBusinessLogic.BusinessLogics
}
}
}
}
}
private static OrderType GetOrderType(string orderTitle) => orderTitle switch
{

View File

@ -30,6 +30,10 @@ namespace DepartmentBusinessLogic.ViewModels
[MapConfiguration("StudentGroup.ToString", IsDifficle = true)]
public string StudentGroupName { get; set; }
[ViewModelControlElementProperty("Идентификатор универа", ControlType.ControlString, MustHaveValue = true, ReadOnly = true)]
[MapConfiguration("Iduniv")]
public string Iduniv { get; set; }
[ViewModelControlListProperty("Номер зачетки")]
[ViewModelControlElementProperty("Номер зачетки", ControlType.ControlString, MustHaveValue = true, ReadOnly = true)]
[MapConfiguration("NumberOfBook")]

View File

@ -4,6 +4,7 @@ using DepartmentBusinessLogic.BindingModels;
using DepartmentBusinessLogic.Interfaces;
using DepartmentBusinessLogic.ViewModels;
using Microsoft.EntityFrameworkCore;
using ModuleTools.Extensions;
using ModuleTools.Models;
using System;
using System.Linq;
@ -56,5 +57,23 @@ namespace DepartmentDatabaseImplementation.Implementations
protected override IQueryable<Student> IncludingWhenReading(IQueryable<Student> query) => query.Include(x => x.StudentGroup).Include(x => x.User);
protected override IQueryable<Student> OrderingWhenReading(IQueryable<Student> query) => query.OrderBy(x => x.StudentGroup.AcademicCourse).ThenBy(x => x.StudentGroup.GroupNumber).ThenBy(x => x.LastName).ThenBy(x => x.FirstName);
protected override bool AdditionalCheckForSingleGet(StudentGetBindingModel model)
{
if (model.NumberOfBook.IsNotEmpty())
{
return true;
}
return base.AdditionalCheckForSingleGet(model);
}
protected override Student GetSingleRecord(IQueryable<Student> list, StudentGetBindingModel model)
{
if (model.NumberOfBook.IsNotEmpty())
{
return list.FirstOrDefault(x => x.NumberOfBook == model.NumberOfBook);
}
return base.GetSingleRecord(list, model);
}
}
}