DepartmentProject/DepartmentPortal/Department/DepartmentDatabaseImplementation.csproj/Implementations/AbstractGenerticEntityService/AcademicPlanService.cs

459 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CoreDatabase;
using CoreDatabase.Models.Department;
using CoreModels.Enums.Department;
using DepartmentContract.BindingModels;
using DepartmentContract.Services.IGenericEntityService;
using DepartmentContract.ViewModels;
using DepartmentDatabaseImplementation.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using ToolsModule.ManagmentEntity;
using ToolsModule.ManagmentExtension;
namespace DepartmentDatabaseImplementation.Implementations.AbstractGenerticEntityService
{
/// <summary>
/// Реализация IAcademicPlanService
/// </summary>
public class AcademicPlanService :
AbstractGenerticEntityService<AcademicPlanGetBindingModel, AcademicPlanSetBindingModel, AcademicPlan, AcademicPlanListViewModel, AcademicPlanViewModel>,
IAcademicPlanService
{
protected override OperationResultModel AdditionalCheckingWhenAdding(DbContext context, AcademicPlanSetBindingModel model) => OperationResultModel.Success(null);
protected override OperationResultModel AdditionalCheckingWhenDeleting(DbContext context, AcademicPlan entity, AcademicPlanGetBindingModel model) => OperationResultModel.Success(null);
protected override IQueryable<AcademicPlan> AdditionalCheckingWhenReadingList(IQueryable<AcademicPlan> query, AcademicPlanGetBindingModel model)
{
if (model.EducationDirectionId.HasValue)
{
query = query.Where(x => x.EducationDirectionId == model.EducationDirectionId.Value);
}
return query;
}
protected override OperationResultModel AdditionalCheckingWhenUpdateing(DbContext context, AcademicPlanSetBindingModel model) => OperationResultModel.Success(null);
protected override void AdditionalDeleting(DbContext context, AcademicPlan entity, AcademicPlanGetBindingModel model)
{
var records = context.Set<AcademicPlanRecord>().Where(x => x.AcademicPlanId == model.Id);
foreach (var record in records)
{
var hours = context.Set<AcademicPlanRecordTimeNormHour>().Where(x => x.AcademicPlanRecordId == record.Id);
foreach (var hour in hours)
{
hour.IsDeleted = true;
hour.DateDelete = DateTime.Now;
}
context.SaveChanges();
record.IsDeleted = true;
record.DateDelete = DateTime.Now;
}
context.SaveChanges();
}
protected override AcademicPlan GetUniqueEntity(AcademicPlanSetBindingModel model, DbContext context) => context.Set<AcademicPlan>().FirstOrDefault(x => x.EducationDirectionId == model.EducationDirectionId && x.YearEntrance == model.YearEntrance && x.Id != model.Id);
protected override IQueryable<AcademicPlan> IncludingWhenReading(IQueryable<AcademicPlan> query) => query.Include(x => x.EducationDirection);
protected override IQueryable<AcademicPlan> OrderingWhenReading(IQueryable<AcademicPlan> query) => query.OrderBy(x => x.EducationDirection.Cipher).ThenBy(x => x.YearEntrance);
public OperationResultModel LoadPlx(AcademicPlanLoadPlxModel model)
{
using var context = DatabaseManager.GetContext;
using var transaction = context.Database.BeginTransaction();
var result = new OperationResultModel();
try
{
#region Получаем настройки
//Получаем номер кафедры
var kafedraNumber = context.EnviromentSettings.FirstOrDefault(x => x.Key == "Кафедра");
if (kafedraNumber == null)
{
throw new Exception("Настройки среды. Не найден ключ Кафедра");
}
#endregion
var academicPlan = context.AcademicPlans.Include(x => x.EducationDirection).FirstOrDefault(x => x.Id == model.AcademicPlanId && !x.IsDeleted && x.EducationDirectionId.HasValue);
if (academicPlan == null)
{
return OperationResultModel.Error("Error:", "Учебный план не найден", ResultServiceStatusCode.NotFound);
}
#region помечаем как удаленные все записи плана, потом все найденные восстановим
var aprs = context.AcademicPlanRecords.Where(x => x.AcademicPlanId == academicPlan.Id).ToList();
foreach (var apr in aprs)
{
var apres = context.AcademicPlanRecordTimeNormHours.Where(x => x.AcademicPlanRecordId == apr.Id);
foreach (var apre in apres)
{
apre.IsDeleted = true;
apre.DateDelete = DateTime.Now;
}
apr.IsDeleted = true;
apr.DateDelete = DateTime.Now;
context.SaveChanges();
}
#endregion
var xml = XDocument.Load(model.FileName)?.Element("Документ")?.Elements()?.Elements()?.Elements();
if (xml != null)
{
var plxModel = new ParsPlxModel
{
AcademicPlanId = academicPlan.Id,
BlockTypes = new(),
DisicplineTypes = new(),
DisciplineBlocks = new(),
TimeNorms = new(),
Practics = new(),
Hours = new(),
Disciplines = new()
};
#region СправочникВидОбъекта - виды дисциплин - базовая, алтернативная и т.п.
foreach (var elem in xml.Where(x => x.Name.LocalName == "СправочникВидОбъекта"))
{
plxModel.DisicplineTypes.Add((TypeName: elem.Attribute("Наименование").Value, Code: elem.Attribute("Код").Value));
}
#endregion
#region ПланыЦиклы
foreach (var elem in xml.Where(x => x.Name.LocalName == "ПланыЦиклы"))
{
plxModel.BlockTypes.Add(new BlueAsteriskBlockType
{
Identificator = elem.Attribute("Идентификатор").Value,
Code = elem.Attribute("Код").Value,
BlockName = elem.Attribute("Цикл").Value,
IsFacultative = Convert.ToBoolean(elem.Attribute("Факультативы").Value)
});
}
#endregion
#region СправочникТипОбъекта - блоки дисциплин
foreach (var elem in xml.Where(x => x.Name.LocalName == "СправочникТипОбъекта"))
{
var disciplineBlock = context.DisciplineBlocks.FirstOrDefault(x => x.DisciplineBlockBlueAsteriskName == elem.Attribute("Название").Value);
if (disciplineBlock != null)
{
plxModel.DisciplineBlocks.Add((
Code: elem.Attribute("Код").Value,
Entity: disciplineBlock
));
}
}
#endregion
#region СправочникВидыРабот - нормы времени
foreach (var elem in xml.Where(x => x.Name.LocalName == "СправочникВидыРабот"))
{
if (!plxModel.TimeNorms.Exists(x => x.Code == elem.Attribute("Код").Value))
{
var timeNorms = context.TimeNorms.Where(x => x.KindOfLoadBlueAsteriskName == elem.Attribute("Название").Value);
foreach (var tn in timeNorms)
{
plxModel.TimeNorms.Add((
Code: elem.Attribute("Код").Value,
Entity: tn
));
}
}
}
#endregion
#region СправочникВидыПрактик - нормы времени (практики)
foreach (var elem in xml.Where(x => x.Name.LocalName == "СправочникВидыПрактик"))
{
if (!plxModel.Practics.Exists(x => x.Code == elem.Attribute("Код").Value))
{
var timeNorms = context.TimeNorms.Where(x => x.KindOfLoadBlueAsteriskPracticName == elem.Attribute("Наименование").Value);
foreach (var tn in timeNorms)
{
plxModel.Practics.Add((
Code: elem.Attribute("Код").Value,
Entity: tn
));
}
}
}
#endregion
#region ПланыНовыеЧасы - часы по дисциплинам
var attributeNames = plxModel.TimeNorms.Select(x => x.Entity.KindOfLoadBlueAsteriskAttributeName).Distinct();
foreach (var elem in xml.Where(x => x.Name.LocalName == "ПланыНовыеЧасы"))
{
var objectCode = elem.Attribute("КодОбъекта")?.Value;
if (objectCode.IsEmpty())
{
throw new Exception(string.Format("Не найден атрибут КодОбъекта"));
}
var timeNormCode = elem.Attribute("КодВидаРаботы")?.Value;
if (timeNormCode.IsEmpty())
{
throw new Exception(string.Format("Не найден атрибут КодВидаРаботы"));
}
var attributeKurs = elem.Attribute("Курс")?.Value;
if (attributeKurs.IsEmpty())
{
throw new Exception(string.Format("Не найдена атрибут Курс"));
}
var attributeSemester = elem.Attribute("Семестр")?.Value;
if (attributeSemester.IsEmpty())
{
throw new Exception(string.Format("Не найдена атрибут Семестр"));
}
var semester = attributeKurs switch
{
"1" => (attributeSemester == "1") ? Semester.Первый : Semester.Второй,
"2" => (attributeSemester == "1") ? Semester.Третий : Semester.Четвертый,
"3" => (attributeSemester == "1") ? Semester.Пятый : Semester.Шестой,
"4" => (attributeSemester == "1") ? Semester.Седьмой : Semester.Восьмой,
_ => Semester.Первый,
};
var hours = new Dictionary<string, decimal>();
foreach (var attr in attributeNames)
{
if (attr.IsNotEmpty())
{
var hour = elem.Attribute(attr)?.Value;
if (hour.IsNotEmpty() && !hours.ContainsKey(attr))
{
if (decimal.TryParse(hour, out decimal h))
{
hours.Add(attr, h);
}
else
{
if (hour.Contains('.'))
{
hour = hour.Replace('.', ',');
}
else if (hour.Contains(','))
{
hour = hour.Replace(',', '.');
}
if (decimal.TryParse(hour, out h))
{
hours.Add(attr, h);
}
}
}
}
}
plxModel.Hours.Add((
DisciplineCode: objectCode,
TimeNormCode: timeNormCode,
Semester: semester,
plxModel.TimeNorms.FirstOrDefault(x => x.Code == timeNormCode).Entity,
Hours: hours
));
}
#endregion
#region ПланыСтроки - сами записи учебного плана
foreach (var elem in xml.Where(x => x.Name.LocalName == "ПланыСтроки"))
{
#region получение дисциплины
var disciplineBlock = plxModel.DisciplineBlocks.FirstOrDefault(x => x.Code == elem.Attribute("ТипОбъекта")?.Value).Entity;
if (disciplineBlock == null)
{
return OperationResultModel.Error("ошибка", $"Не найден блок дисциплин с кодом {elem.Attribute("ТипОбъекта")?.Value}", ResultServiceStatusCode.NotFound);
}
var disciplineName = elem.Attribute("Дисциплина")?.Value;
// ищем по названию в планах дисциплину
var discipline = context.Disciplines.FirstOrDefault(x => x.DisciplineBlueAsteriskName == disciplineName);
if (discipline == null)
{
// ищем по названию дисциплину
discipline = context.Disciplines.FirstOrDefault(x => x.DisciplineName == disciplineName);
if (discipline == null)
{
discipline = new Discipline
{
DisciplineName = disciplineName,
DisciplineBlockId = disciplineBlock.Id,
DisciplineBlueAsteriskName = disciplineName
};
context.Disciplines.Add(discipline);
context.SaveChanges();
}
else
{
discipline.DisciplineBlueAsteriskName = disciplineName;
context.SaveChanges();
}
}
plxModel.Discipline = (
Code: elem.Attribute("Код")?.Value,
Practic: elem.Attribute("ВидПрактики")?.Value,
Entity: discipline
);
plxModel.Disciplines.Add(plxModel.Discipline);
#endregion
//смотрим код кафедры
bool inKafedra = elem.Attribute("КодКафедры")?.Value == kafedraNumber.Value;
bool isFacultative = elem.Attribute("ДисциплинаКод")?.Value?.StartsWith("ФТД") ?? false;
var zet = elem.Attribute("ЗЕТфакт")?.Value;
// вытаскиваем часы по дисциплине
foreach (var hour in plxModel.Hours.Where(x => x.DisciplineCode == plxModel.Discipline.Code))
{
#region Родитель
AcademicPlanRecord parent = null;
var parentValue = elem.Attribute("КодРодителя")?.Value;
if (parentValue.IsNotEmpty())
{
var parentDiscipilne = plxModel.Disciplines.FirstOrDefault(x => x.Code == parentValue);
if (parentDiscipilne == default)
{
return OperationResultModel.Error("ошибка", $"Не найдена родительская дисциплина с кодом {parentValue}", ResultServiceStatusCode.NotFound);
}
parent = context.AcademicPlanRecords.FirstOrDefault(apr =>
apr.AcademicPlanId == model.AcademicPlanId &&
apr.DisciplineId == parentDiscipilne.Entity.Id &&
apr.Semester == hour.Semester);
if (parent == null)
{
// возмжно, родитель будет описан позже, заполняем данными дочернего класса пока что
parent = new AcademicPlanRecord
{
AcademicPlanId = model.AcademicPlanId,
DisciplineId = parentDiscipilne.Entity.Id,
InDepartment = inKafedra,
Semester = hour.Semester,
Zet = zet.IsNotEmpty() ? Convert.ToInt32(zet) : 0,
IsParent = true,
IsFacultative = isFacultative
};
context.AcademicPlanRecords.Add(parent);
context.SaveChanges();
}
else if (parent.IsDeleted)
{
parent.IsDeleted = false;
parent.DateDelete = null;
context.SaveChanges();
}
if (!parent.IsParent)
{
parent.IsParent = true;
context.SaveChanges();
}
}
#endregion
#region Запись учебного плана
var record = context.AcademicPlanRecords.FirstOrDefault(apr =>
apr.AcademicPlanId == model.AcademicPlanId &&
apr.DisciplineId == discipline.Id &&
apr.Semester == hour.Semester);
if (record == null)
{
record = new AcademicPlanRecord
{
AcademicPlanId = model.AcademicPlanId,
DisciplineId = discipline.Id,
Zet = zet.IsNotEmpty() ? Convert.ToInt32(zet) : 0,
Semester = hour.Semester,
AcademicPlanRecordParentId = parent?.Id,
IsParent = false,
IsFacultative = isFacultative,
InDepartment = inKafedra
};
context.AcademicPlanRecords.Add(record);
context.SaveChanges();
}
else if (record.IsDeleted)
{
record.IsDeleted = false;
record.DateDelete = null;
context.SaveChanges();
}
#endregion
#region
if (record != null)
{
var timeNorms = new List<TimeNorm>();
// если перед нами практика, то выбираем только один нужный тип нагрузки
if (plxModel.Discipline.Practic.IsNotEmpty())
{
timeNorms.AddRange(plxModel.Practics.Where(x => x.Code == hour.TimeNormCode &&
x.Entity.DisciplineBlockId == plxModel.Discipline.Entity.DisciplineBlockId &&
(!x.Entity.TimeNormEducationDirectionQualification.HasValue ||
x.Entity.TimeNormEducationDirectionQualification == academicPlan.EducationDirection.Qualification) &&
x.Code == plxModel.Discipline.Practic).Select(x => x.Entity));
}
else
{
timeNorms.AddRange(plxModel.TimeNorms.Where(x => x.Code == hour.TimeNormCode &&
x.Entity.DisciplineBlockId == plxModel.Discipline.Entity.DisciplineBlockId &&
(!x.Entity.TimeNormEducationDirectionQualification.HasValue ||
x.Entity.TimeNormEducationDirectionQualification == academicPlan.EducationDirection.Qualification)).Select(x => x.Entity));
}
foreach (var timeNorm in timeNorms)
{
decimal planHours = 1;
if (timeNorm.KindOfLoadBlueAsteriskAttributeName.IsNotEmpty())
{
if (!hour.Hours.ContainsKey(timeNorm.KindOfLoadBlueAsteriskAttributeName))
{
return OperationResultModel.Error("ошибка",
$"Не найдена атрибут {timeNorm.KindOfLoadBlueAsteriskAttributeName} по дисциплине с кодом {plxModel.Discipline.Code}", ResultServiceStatusCode.NotFound);
}
planHours = Math.Abs(hour.Hours[timeNorm.KindOfLoadBlueAsteriskAttributeName]);
}
var recordelement = context.AcademicPlanRecordTimeNormHours.FirstOrDefault(apre =>
apre.AcademicPlanRecordId == record.Id &&
apre.TimeNormId == timeNorm.Id);
if (recordelement == null)
{
context.AcademicPlanRecordTimeNormHours.Add(new AcademicPlanRecordTimeNormHour
{
AcademicPlanRecordId = record.Id,
TimeNormId = timeNorm.Id,
PlanHours = planHours
});
}
else
{
if (recordelement.IsDeleted)
{
recordelement.IsDeleted = false;
recordelement.DateDelete = null;
}
recordelement.PlanHours = planHours;
}
context.SaveChanges();
}
}
#endregion
}
}
#endregion
}
transaction.Commit();
return result;
}
catch (Exception ex)
{
transaction.Rollback();
return OperationResultModel.Error(ex, ResultServiceStatusCode.Error);
}
}
}
}