загрузка учбеных планов

This commit is contained in:
kotcheshir73 2021-04-11 20:49:26 +04:00
parent 754edb3e2a
commit 4008a5e2a5
24 changed files with 1900 additions and 52 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,100 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace DatabaseCore.Migrations
{
public partial class ChangeAcademPlan : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AcademicPlanRecordTimeNormHours_TimeNorms_TimeNormId",
table: "AcademicPlanRecordTimeNormHours");
migrationBuilder.DropForeignKey(
name: "FK_AcademicPlans_EducationDirections_EducationDirectionId",
table: "AcademicPlans");
migrationBuilder.DropIndex(
name: "IX_AcademicPlans_EducationDirectionId_YearEntrance",
table: "AcademicPlans");
migrationBuilder.AlterColumn<Guid>(
name: "EducationDirectionId",
table: "AcademicPlans",
type: "uniqueidentifier",
nullable: true,
oldClrType: typeof(Guid),
oldType: "uniqueidentifier");
migrationBuilder.CreateIndex(
name: "IX_AcademicPlans_EducationDirectionId_YearEntrance",
table: "AcademicPlans",
columns: new[] { "EducationDirectionId", "YearEntrance" },
unique: true,
filter: "[EducationDirectionId] IS NOT NULL");
migrationBuilder.AddForeignKey(
name: "FK_AcademicPlanRecordTimeNormHours_TimeNorms_TimeNormId",
table: "AcademicPlanRecordTimeNormHours",
column: "TimeNormId",
principalTable: "TimeNorms",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
migrationBuilder.AddForeignKey(
name: "FK_AcademicPlans_EducationDirections_EducationDirectionId",
table: "AcademicPlans",
column: "EducationDirectionId",
principalTable: "EducationDirections",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AcademicPlanRecordTimeNormHours_TimeNorms_TimeNormId",
table: "AcademicPlanRecordTimeNormHours");
migrationBuilder.DropForeignKey(
name: "FK_AcademicPlans_EducationDirections_EducationDirectionId",
table: "AcademicPlans");
migrationBuilder.DropIndex(
name: "IX_AcademicPlans_EducationDirectionId_YearEntrance",
table: "AcademicPlans");
migrationBuilder.AlterColumn<Guid>(
name: "EducationDirectionId",
table: "AcademicPlans",
type: "uniqueidentifier",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
oldClrType: typeof(Guid),
oldType: "uniqueidentifier",
oldNullable: true);
migrationBuilder.CreateIndex(
name: "IX_AcademicPlans_EducationDirectionId_YearEntrance",
table: "AcademicPlans",
columns: new[] { "EducationDirectionId", "YearEntrance" },
unique: true);
migrationBuilder.AddForeignKey(
name: "FK_AcademicPlanRecordTimeNormHours_TimeNorms_TimeNormId",
table: "AcademicPlanRecordTimeNormHours",
column: "TimeNormId",
principalTable: "TimeNorms",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_AcademicPlans_EducationDirections_EducationDirectionId",
table: "AcademicPlans",
column: "EducationDirectionId",
principalTable: "EducationDirections",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -30,7 +30,7 @@ namespace DatabaseCore.Migrations
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<Guid>("EducationDirectionId")
b.Property<Guid?>("EducationDirectionId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsDeleted")
@ -45,7 +45,8 @@ namespace DatabaseCore.Migrations
b.HasKey("Id");
b.HasIndex("EducationDirectionId", "YearEntrance")
.IsUnique();
.IsUnique()
.HasFilter("[EducationDirectionId] IS NOT NULL");
b.ToTable("AcademicPlans");
});
@ -854,9 +855,7 @@ namespace DatabaseCore.Migrations
{
b.HasOne("DatabaseCore.Models.Department.EducationDirection", "EducationDirection")
.WithMany("AcademicPlans")
.HasForeignKey("EducationDirectionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
.HasForeignKey("EducationDirectionId");
b.Navigation("EducationDirection");
});

View File

@ -17,9 +17,8 @@ namespace DatabaseCore.Models.Department
public class AcademicPlan : BaseEntity, IEntitySecurityExtenstion<AcademicPlan>
{
[DataMember]
[Required(ErrorMessage = "required")]
[MapConfiguration("EducationDirectionId")]
public Guid EducationDirectionId { get; set; }
public Guid? EducationDirectionId { get; set; }
[DataMember]
[Required(ErrorMessage = "required")]

View File

@ -10,7 +10,6 @@ using ModuleTools.Enums;
using ModuleTools.Extensions;
using ModuleTools.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
@ -28,7 +27,7 @@ namespace DesktopTools.Controls
/// <summary>
/// Объект бизнес-логики для получения данных
/// </summary>
private readonly BL _businessLogic;
protected readonly BL _businessLogic;
/// <summary>
/// Методы для реализации в generic-контроле
@ -45,7 +44,7 @@ namespace DesktopTools.Controls
/// </summary>
private readonly int _defaultControlWidth = 350;
private E _element = null;
protected E _element = null;
/// <summary>
/// Событие, вызываемое при закрытии контрола

View File

@ -42,6 +42,10 @@ namespace DesktopTools.Controls
private readonly object _lockObject = new();
private bool _usePages = false;
private bool _useNames = false;
/// <summary>
/// Объект бизнес-логики для получения данных
/// </summary>
@ -236,12 +240,14 @@ namespace DesktopTools.Controls
// пагинация по страницам
if (config.CountElementsOnPage.HasValue)
{
_usePages = true;
toolStripTextBoxCountRecords.Text = config.CountElementsOnPage.Value.ToString();
toolStripLabelPageName.Visible = toolStripComboBoxPageNames.Visible = false;
}
// пагинация по названиям
else if (config.PageNamesForPagination != null)
if (config.PageNamesForPagination != null)
{
_useNames = true;
toolStripButtonPrev.Visible = toolStripLabelPage.Visible = toolStripTextBoxPage.Visible = toolStripLabelCountPages.Visible =
toolStripLabelCountRecords.Visible = toolStripTextBoxCountRecords.Visible = toolStripButtonNext.Visible = false;
@ -264,7 +270,12 @@ namespace DesktopTools.Controls
{
panelHeader.Visible = false;
toolStripButtonClose.Visible = false;
toolStripFooter.Visible = false;
toolStripSeparator6.Visible = false;
toolStripButtonSelect.Visible = false;
}
// Открытие через родительский элемент
if (_openMode == ControlOpenMode.Select)
{
toolStripSeparator6.Visible = true;
toolStripButtonSelect.Visible = true;
}
@ -408,10 +419,8 @@ namespace DesktopTools.Controls
}
}
// если включена пагинация
else if (toolStripFooter.Visible)
{
// постраничная
if (toolStripTextBoxPage.Visible)
if (_usePages)
{
if (int.TryParse(toolStripTextBoxPage.Text, out int page) && int.TryParse(toolStripTextBoxCountRecords.Text.ToString(), out int count))
{
@ -420,7 +429,7 @@ namespace DesktopTools.Controls
}
}
// поименная
else if (toolStripComboBoxPageNames.Visible)
if (_useNames)
{
if (toolStripComboBoxPageNames.SelectedItem is PageNamesForPaginationModel key)
{
@ -431,7 +440,6 @@ namespace DesktopTools.Controls
}
}
}
}
await Task.Run(() => data = _businessLogic.GetList(model));
if (data == null && _businessLogic.Errors.Count > 0)
{
@ -569,7 +577,7 @@ namespace DesktopTools.Controls
control.ParentId = ParentId;
control.ParentPropertyName = ParentPropertyName;
}
if (toolStripFooter.Visible && toolStripComboBoxPageNames.Visible)
else if (toolStripFooter.Visible && toolStripComboBoxPageNames.Visible)
{
if (toolStripComboBoxPageNames.SelectedItem is PageNamesForPaginationModel key)
{
@ -605,6 +613,24 @@ namespace DesktopTools.Controls
}
}
/// <summary>
/// Получение настроек для контрола
/// </summary>
/// <returns></returns>
private ControlViewEntityListConfiguration GetConfig() => _genericControlViewEntityList?.GetConfigControl();
/// <summary>
/// Получение списка идентификаторов выбранных записей
/// </summary>
/// <returns></returns>
protected List<Guid> GetSelectedIds()
{
List<Guid> guids = new();
foreach (DataGridViewRow selected in dataGridViewList.SelectedRows)
{
guids.Add(new Guid(selected.Cells[0].Value.ToString()));
}
return guids;
}
}
}

View File

@ -29,6 +29,7 @@ namespace DesktopTools.Controls
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.toolStripMenu = new System.Windows.Forms.ToolStrip();
this.toolStripButtonAdd = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
@ -62,6 +63,7 @@ namespace DesktopTools.Controls
this.dataGridViewList = new System.Windows.Forms.DataGridView();
this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripButtonSelect = new System.Windows.Forms.ToolStripButton();
this.contextMenuStripDataGrid = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenu.SuspendLayout();
this.panelHeader.SuspendLayout();
this.panelSearch.SuspendLayout();
@ -328,6 +330,7 @@ namespace DesktopTools.Controls
this.dataGridViewList.AllowUserToDeleteRows = false;
this.dataGridViewList.AllowUserToResizeRows = false;
this.dataGridViewList.BackgroundColor = System.Drawing.SystemColors.ControlLightLight;
this.dataGridViewList.ContextMenuStrip = this.contextMenuStripDataGrid;
this.dataGridViewList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridViewList.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridViewList.Location = new System.Drawing.Point(0, 142);
@ -354,6 +357,11 @@ namespace DesktopTools.Controls
this.toolStripButtonSelect.Text = "Выбрать";
this.toolStripButtonSelect.Visible = false;
//
// contextMenuStripDataGrid
//
this.contextMenuStripDataGrid.Name = "contextMenuStripDataGrid";
this.contextMenuStripDataGrid.Size = new System.Drawing.Size(61, 4);
//
// ControlViewEntityList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);

View File

@ -54,7 +54,7 @@ namespace ModuleTools.BusinessLogics
var result = Service.Read(model);
if (!result.IsSucceeded)
{
Errors.AddRange(Errors);
Errors.AddRange(result.Errors);
return null;
}
@ -85,7 +85,7 @@ namespace ModuleTools.BusinessLogics
var result = Service.Read(model);
if (!result.IsSucceeded)
{
Errors.AddRange(Errors);
Errors.AddRange(result.Errors);
return null;
}
return result.Result as E;
@ -114,7 +114,7 @@ namespace ModuleTools.BusinessLogics
var result = Service.Create(model);
if (!result.IsSucceeded)
{
Errors.AddRange(Errors);
Errors.AddRange(result.Errors);
return null;
}
@ -144,7 +144,7 @@ namespace ModuleTools.BusinessLogics
var result = Service.Update(model);
if (!result.IsSucceeded)
{
Errors.AddRange(Errors);
Errors.AddRange(result.Errors);
return null;
}
@ -174,7 +174,7 @@ namespace ModuleTools.BusinessLogics
var result = Service.Delete(model);
if (!result.IsSucceeded)
{
Errors.AddRange(Errors);
Errors.AddRange(result.Errors);
return false;
}

View File

@ -18,9 +18,8 @@ namespace DepartmentBusinessLogic.BindingModels
/// </summary>
public class AcademicPlanSetBindingModel : SetBindingModel
{
[Required(ErrorMessage = "required")]
[MapConfiguration("EducationDirectionId")]
public Guid EducationDirectionId { get; set; }
public Guid? EducationDirectionId { get; set; }
[Required(ErrorMessage = "required")]
[MapConfiguration("YearEntrance")]
@ -30,4 +29,14 @@ namespace DepartmentBusinessLogic.BindingModels
[MapConfiguration("YearFinish")]
public int YearFinish { get; set; }
}
/// <summary>
/// Модель для зазгрузки планов
/// </summary>
public class AcademicPlanLoadPlxModel
{
public Guid AcademicPlanId { get; set; }
public string FileName { get; set; }
}
}

View File

@ -27,12 +27,6 @@ namespace DepartmentBusinessLogic.BindingModels
[MapConfiguration("DisciplineBlockOrder")]
public int DisciplineBlockOrder { get; set; }
/// <summary>
/// Используется только в расчетах, не сохраняется
/// </summary>
[MapConfiguration("DisciplineBlockBlueAsteriskCode")]
public string DisciplineBlockBlueAsteriskCode { get; set; }
[MapConfiguration("DisciplineBlockBlueAsteriskName")]
public string DisciplineBlockBlueAsteriskName { get; set; }
}

View File

@ -12,5 +12,22 @@ namespace DepartmentBusinessLogic.BusinessLogics
public class AcademicPlanBusinessLogic : GenericBusinessLogic<AcademicPlanGetBindingModel, AcademicPlanSetBindingModel, AcademicPlanListViewModel, AcademicPlanViewModel>
{
public AcademicPlanBusinessLogic(IAcademicPlanService service) : base(service, "Учебные Планы", AccessOperation.УчебныеПланы) { }
/// <summary>
/// Загрузка учебного плана
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public bool LoadPlx(AcademicPlanLoadPlxModel model)
{
Errors.Clear();
var result = (Service as IAcademicPlanService).LoadPlx(model);
if (!result.IsSucceeded)
{
Errors.AddRange(result.Errors);
return false;
}
return true;
}
}
}

View File

@ -1,10 +1,19 @@
using DepartmentBusinessLogic.BindingModels;
using ModuleTools.Interfaces;
using ModuleTools.Models;
namespace DepartmentBusinessLogic.Interfaces
{
/// <summary>
/// Хранение учебных планов
/// </summary>
public interface IAcademicPlanService : IGenerticEntityService<AcademicPlanGetBindingModel, AcademicPlanSetBindingModel> { }
public interface IAcademicPlanService : IGenerticEntityService<AcademicPlanGetBindingModel, AcademicPlanSetBindingModel>
{
/// <summary>
/// Загрузка учебного плана
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public OperationResultModel LoadPlx(AcademicPlanLoadPlxModel model);
}
}

View File

@ -35,7 +35,7 @@ namespace DepartmentBusinessLogic.ViewModels
[MapConfiguration("InDepartment")]
public bool InDepartment { get; set; }
[ViewModelControlListProperty("На кафедре", ColumnWidth = 80)]
[ViewModelControlListProperty("На кафедре", ColumnWidth = 100)]
public string InDepartmentValue => InDepartment ? "Да" : "Нет";
[ViewModelControlElementProperty("Семестр", ControlType.ControlEnum, MustHaveValue = true)]
@ -61,7 +61,7 @@ namespace DepartmentBusinessLogic.ViewModels
[ViewModelControlListProperty("ДВ", ColumnWidth = 50)]
public string IsParentValue => IsParent ? "Да" : "Нет";
[ViewModelControlListProperty("По выбору", ColumnWidth = 80)]
[ViewModelControlListProperty("По выбору", ColumnWidth = 100)]
public string IsChildValue => AcademicPlanRecordParentId.HasValue ? "Да" : "Нет";
/// <summary>

View File

@ -13,26 +13,26 @@ namespace DepartmentBusinessLogic.ViewModels
/// <summary>
/// Элемент учебного плана
/// </summary>
[ViewModelControlElementClass(HaveDependenceEntities = true, Width = 800, Height = 500)]
[ViewModelControlElementClass(HaveDependenceEntities = true, Width = 1200, Height = 800)]
[ViewModelControlElementDependenceEntity(Title = "Записи плана", Order = 1, ParentPropertyName = "AcademicPlanId",
ControlTypeObject = "DepartmentWindowsDesktop.EntityControls.ControlAcademicPlanRecordList, DepartmentWindowsDesktop")]
public class AcademicPlanViewModel : ElementViewModel
{
[ViewModelControlElementProperty("Направление", ControlType.ControlGuid, MustHaveValue = true, ReadOnly = false, ControlTypeObject = "DepartmentWindowsDesktop.EntityControls.ControlEducationDirectionList, DepartmentWindowsDesktop")]
[ViewModelControlElementProperty("Направление", ControlType.ControlGuid, MustHaveValue = false, ReadOnly = false, ControlTypeObject = "DepartmentWindowsDesktop.EntityControls.ControlEducationDirectionList, DepartmentWindowsDesktop")]
[MapConfiguration("EducationDirectionId")]
public Guid EducationDirectionId { get; set; }
public Guid? EducationDirectionId { get; set; }
[ViewModelControlListProperty("Направление")]
[MapConfiguration("EducationDirection.Cipher", IsDifficle = true)]
public string EducationDirectionCipher { get; set; }
[ViewModelControlListProperty("Дата начала", ColumnWidth = 120)]
[ViewModelControlElementProperty("Дата начала", ControlType.ControlString, MustHaveValue = true)]
[ViewModelControlElementProperty("Дата начала", ControlType.ControlInt, MustHaveValue = true)]
[MapConfiguration("YearEntrance")]
public int YearEntrance { get; set; }
[ViewModelControlListProperty("Дата окончания", ColumnWidth = 120)]
[ViewModelControlElementProperty("Дата окончания", ControlType.ControlString, MustHaveValue = true)]
[ViewModelControlElementProperty("Дата окончания", ControlType.ControlInt, MustHaveValue = true)]
[MapConfiguration("YearFinish")]
public int YearFinish { get; set; }

View File

@ -1,12 +1,20 @@
using DatabaseCore;
using DatabaseCore.Models.Department;
using DepartmentBusinessLogic.BindingModels;
using DepartmentBusinessLogic.Enums;
using DepartmentBusinessLogic.Interfaces;
using DepartmentBusinessLogic.ViewModels;
using DepartmentDatabaseImplementation.Models;
using Microsoft.EntityFrameworkCore;
using ModuleTools.Enums;
using ModuleTools.Extensions;
using ModuleTools.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace DepartmentDatabaseImplementation.Implementations
{
@ -56,5 +64,399 @@ namespace DepartmentDatabaseImplementation.Implementations
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 == (int)hour.Semester);
if (parent == null)
{
// возмжно, родитель будет описан позже, заполняем данными дочернего класса пока что
parent = new AcademicPlanRecord
{
AcademicPlanId = model.AcademicPlanId,
DisciplineId = parentDiscipilne.Entity.Id,
InDepartment = inKafedra,
Semester = (int)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 == (int)hour.Semester);
if (record == null)
{
record = new AcademicPlanRecord
{
AcademicPlanId = model.AcademicPlanId,
DisciplineId = discipline.Id,
Zet = zet.IsNotEmpty() ? Convert.ToInt32(zet) : 0,
Semester = (int)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);
}
}
}
}

View File

@ -0,0 +1,18 @@
namespace DepartmentDatabaseImplementation.Models
{
/// <summary>
/// Вспомогательный класс для загрузки учебных планов по синей звездочке
/// Фиксирует к какому циклу относится дисциплина
/// На данный момент нужна для отсеивания факультативов
/// </summary>
public class BlueAsteriskBlockType
{
public string BlockName { get; set; }
public string Identificator { get; set; }
public string Code { get; set; }
public bool IsFacultative { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace DepartmentDatabaseImplementation.Models
{
public class BlueAsteriskNewHour
{
public int Kurs { get; set; }
public int Semester { get; set; }
public string ObjectCode { get; set; }
public string TypeNormCode { get; set; }
public Dictionary<string, decimal> TimeNorms { get; set; }
}
}

View File

@ -0,0 +1,35 @@
using DatabaseCore.Models.Department;
using DepartmentBusinessLogic.BindingModels;
using DepartmentBusinessLogic.Enums;
using System;
using System.Collections.Generic;
using System.Xml;
namespace DepartmentDatabaseImplementation.Models
{
/// <summary>
/// Данные для разбора plx-файла с планом
/// </summary>
public class ParsPlxModel
{
public Guid AcademicPlanId { get; set; }
public XmlNode Node { get; set; }
public List<(string TypeName, string Code)> DisicplineTypes { get; set; }
public List<BlueAsteriskBlockType> BlockTypes { get; set; }
public List<(string Code, DisciplineBlock Entity)> DisciplineBlocks { get; set; }
public (string Code, string Practic, Discipline Entity) Discipline { get; set; }
public List<(string Code, string Practic, Discipline Entity)> Disciplines { get; set; }
public List<(string Code, TimeNorm Entity)> TimeNorms { get; set; }
public List<(string Code, TimeNorm Entity)> Practics { get; set; }
public List<(string DisciplineCode, string TimeNormCode, Semester Semester, TimeNorm Entity, Dictionary<string, decimal> Hours)> Hours { get; set; }
}
}

View File

@ -7,6 +7,7 @@
<ItemGroup>
<ProjectReference Include="..\..\Common\DesktopTools\DesktopTools.csproj" />
<ProjectReference Include="..\..\Security\SecurityBusinessLogic\SecurityBusinessLogic.csproj" />
<ProjectReference Include="..\DepartmentBusinessLogic\DepartmentBusinessLogic.csproj" />
</ItemGroup>

View File

@ -2,9 +2,12 @@
using DepartmentBusinessLogic.BusinessLogics;
using DepartmentBusinessLogic.ViewModels;
using DesktopTools.Controls;
using DesktopTools.Helpers;
using DesktopTools.Interfaces;
using DesktopTools.Models;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DepartmentWindowsDesktop.EntityControls
{
@ -25,6 +28,42 @@ namespace DepartmentWindowsDesktop.EntityControls
public IControl GetInstanceGenericControl() => new ControlAcademicPlanElement() { ControlId = Guid.NewGuid() };
public ControlViewEntityElementConfiguration GetConfigControl() => new();
public ControlViewEntityElementConfiguration GetConfigControl() => new()
{
ControlOnMoveElem = new Dictionary<string, (string Title, EventHandler Event)>
{
{ "ToolStripMenuItemLoadPlan", ("Загрузить план", (object sender, EventArgs e) => { LoadPlx(); }) }
}
};
/// <summary>
/// Загрузка учебного плана
/// </summary>
private void LoadPlx()
{
if (_element != null)
{
var dialog = new OpenFileDialog
{
Filter = "plx|*.plx"
};
if (dialog.ShowDialog() == DialogResult.OK)
{
var result = _businessLogic.LoadPlx(new AcademicPlanLoadPlxModel
{
AcademicPlanId = _element.Id,
FileName = dialog.FileName
});
if (result)
{
DialogHelper.MessageInformation("Загрузка прошла успешно", "Результат");
}
else
{
DialogHelper.MessageException(_businessLogic.Errors, $"Ошибки при загрузке плана");
}
}
}
}
}
}

View File

@ -3,11 +3,13 @@ using DepartmentBusinessLogic.BusinessLogics;
using DepartmentBusinessLogic.ViewModels;
using DesktopTools.Controls;
using DesktopTools.Enums;
using DesktopTools.Helpers;
using DesktopTools.Interfaces;
using DesktopTools.Models;
using ModuleTools.Enums;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DepartmentWindowsDesktop.EntityControls
{
@ -21,7 +23,7 @@ namespace DepartmentWindowsDesktop.EntityControls
public ControlAcademicPlanList()
{
InitializeComponent();
Title = "Учебнве планы";
Title = "Учебные планы";
ControlId = new Guid("144d098c-ff55-4786-ae63-3105a92990cd");
AccessOperation = AccessOperation.УчебныеПланы;
ControlViewEntityElement = new ControlAcademicPlanElement();
@ -36,7 +38,44 @@ namespace DepartmentWindowsDesktop.EntityControls
HideToolStripButton = new List<ToolStripButtonListNames>
{
ToolStripButtonListNames.toolStripButtonSearch
},
ControlOnMoveElem = new Dictionary<string, (string Title, EventHandler Event)>
{
{ "ToolStripMenuItemLoadPlx", ("Загрузить план", (object sender, EventArgs e) => { LoadPlx(); }) }
}
};
/// <summary>
/// Загрузка учебного плана
/// </summary>
private void LoadPlx()
{
var ids = GetSelectedIds();
if (ids.Count != 1)
{
DialogHelper.MessageException("Должна быть выбрана одна запись", $"Ошибка");
return;
}
var dialog = new OpenFileDialog
{
Filter = "plx|*.plx"
};
if (dialog.ShowDialog() == DialogResult.OK)
{
var result = _businessLogic.LoadPlx(new AcademicPlanLoadPlxModel
{
AcademicPlanId = ids[0],
FileName = dialog.FileName
});
if (result)
{
DialogHelper.MessageInformation("Загрузка прошла успешно", "Результат");
}
else
{
DialogHelper.MessageException(_businessLogic.Errors, $"Ошибки при загрузке плана");
}
}
}
}
}

View File

@ -42,6 +42,7 @@ namespace DepartmentWindowsDesktop.EntityControls
Key = x,
Value = x.ToString()
})?.ToList(),
ParentPropertyName = "Semester",
HideToolStripButton = new List<ToolStripButtonListNames>
{
ToolStripButtonListNames.toolStripButtonSearch

View File

@ -40,6 +40,9 @@ namespace DepartmentWindowsDesktop.EntityControls
}
};
/// <summary>
/// Поиск пользователя под учетку, либо добавление нового, если не найдено
/// </summary>
private void AddUser()
{
var model = new EmployeeSetBindingModel();

View File

@ -37,6 +37,9 @@ namespace DepartmentWindowsDesktop.EntityControls
}
};
/// <summary>
/// Поиск пользователя под учетку, либо добавление нового, если не найдено
/// </summary>
private void AddUser()
{
var model = new LecturerSetBindingModel();