From 5317b7b563ba1354fe8825c5fe4fe52bc5a7bd64 Mon Sep 17 00:00:00 2001 From: Polianin Nikita Date: Sun, 27 Oct 2024 08:25:46 +0300 Subject: [PATCH] feat: add import to excel Made at the request of the customer --- Endpoint/Controllers/V1/ImportController.cs | 165 ++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 Endpoint/Controllers/V1/ImportController.cs diff --git a/Endpoint/Controllers/V1/ImportController.cs b/Endpoint/Controllers/V1/ImportController.cs new file mode 100644 index 0000000..c674d6b --- /dev/null +++ b/Endpoint/Controllers/V1/ImportController.cs @@ -0,0 +1,165 @@ +using Asp.Versioning; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Mirea.Api.DataAccess.Application.Cqrs.Schedule.Queries.GetScheduleList; +using Mirea.Api.Dto.Requests; +using Mirea.Api.Endpoint.Configuration.Model; +using OfficeOpenXml; +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace Mirea.Api.Endpoint.Controllers.V1; + +[ApiVersion("1.0")] +public class ImportController(IMediator mediator, IOptionsSnapshot config) : BaseController +{ + // todo: transfer data to storage + private static string GetFaculty(char c) => + c switch + { + 'У' => "ИТУ", + 'Б' => "ИКБ", + 'Х' => "ИТХТ", + 'Э' => "ИПТИП", + 'Т' => "ИПТИП", + 'Р' => "ИРИ", + 'К' => "ИИИ", + 'И' => "ИИТ", + 'П' => "ИИТ", + _ => throw new ArgumentOutOfRangeException(nameof(c), c, null) + }; + + /// + /// Creates an Excel file based on a schedule filter + /// + /// The request object containing filter criteria. + /// Excel file + [HttpPost("ImportToExcel")] + [Produces("application/vnd.ms-excel")] + public async Task ImportToExcel([FromBody] ScheduleRequest request) + { + var result = (await mediator.Send(new GetScheduleListQuery + { + IsEven = request.IsEven, + DisciplineIds = request.Disciplines, + GroupIds = request.Groups, + LectureHallIds = request.LectureHalls, + ProfessorIds = request.Professors + })).Schedules; + + if (result.Count == 0) + return NoContent(); + + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + using var package = new ExcelPackage(); + var worksheet = package.Workbook.Worksheets.Add("Расписание"); + + int row = 1; + int col = 1; + + worksheet.Cells[row, col++].Value = "День"; + worksheet.Cells[row, col++].Value = "Пара"; + worksheet.Cells[row, col++].Value = "Неделя"; + worksheet.Cells[row, col++].Value = "Время"; + worksheet.Cells[row, col++].Value = "Группа"; + worksheet.Cells[row, col++].Value = "Институт"; + worksheet.Cells[row, col++].Value = "Курс"; + worksheet.Cells[row, col++].Value = "Дисциплина"; + worksheet.Cells[row, col++].Value = "Преподаватель"; + worksheet.Cells[row, col++].Value = "Вид"; + worksheet.Cells[row, col++].Value = "Кампус"; + worksheet.Cells[row, col].Value = "Ауд."; + + row++; + col = 1; + + var pairsDictionary = config.Value.ScheduleSettings!.PairPeriod; + + foreach (var dto in result.GroupBy(s => new + { + s.DayOfWeek, + s.PairNumber, + s.IsEven, + s.DisciplineId, + TypeOfOccupations = string.Join(',', s.TypeOfOccupations.OrderBy(x => x)), + LectureHalls = string.Join(',', s.LectureHalls.OrderBy(x => x)), + Campus = string.Join(',', s.Campus.OrderBy(x => x)), + Professors = string.Join(',', s.Professors.OrderBy(x => x)) + }) + .Select(g => new + { + g.Key.DayOfWeek, + g.Key.PairNumber, + g.Key.IsEven, + g.First().Discipline, + g.First().LectureHalls, + g.First().Campus, + g.First().Professors, + Groups = string.Join('\n', g.Select(x => x.Group)), + + IsExclude = g.First().IsExcludedWeeks, + g.First().TypeOfOccupations, + g.First().Weeks + }) + .ToList()) + { + // День + worksheet.Cells[row, col++].Value = + $"{(int)dto.DayOfWeek} [{CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedDayName(dto.DayOfWeek).ToUpper()}]"; + + // Пара + worksheet.Cells[row, col++].Value = dto.PairNumber + " п"; + + // Неделя + worksheet.Cells[row, col++].Value = $"[{(dto.IsEven ? 2 : 1)}] {(dto.IsEven ? "Четная" : "Нечетная")}"; + + // Время + worksheet.Cells[row, col++].Value = pairsDictionary[dto.PairNumber].Start.ToString(CultureInfo.CurrentCulture); + + // Группа + worksheet.Cells[row, col].Style.WrapText = true; + worksheet.Cells[row, col++].Value = dto.Groups; + + var groupTemplate = dto.Groups.Split('\n')[0]; + + // Институт + worksheet.Cells[row, col++].Value = GetFaculty(groupTemplate[0]); + // Курс + worksheet.Cells[row, col++].Value = groupTemplate[2] == 'М' ? + 'М' : + (24 - int.Parse(groupTemplate.Split(' ')[0].Split('-').TakeLast(1).ElementAt(0)) + 1).ToString(); + + var disciplineAdditional = string.Empty; + + if (dto.IsExclude.HasValue && dto.Weeks != null && dto.Weeks.Any()) + disciplineAdditional += $"{(dto.IsExclude.Value ? "Кр. " : "")}{string.Join(", ", dto.Weeks.OrderBy(x => x))} н. "; + + // Дисциплина + worksheet.Cells[row, col++].Value = disciplineAdditional + dto.Discipline; + + // Преподаватель + worksheet.Cells[row, col++].Value = dto.Professors; + // Вид + worksheet.Cells[row, col++].Value = dto.TypeOfOccupations.FirstOrDefault(); + // Кампус + worksheet.Cells[row, col++].Value = dto.Campus.FirstOrDefault()?.Replace("С-20", "С20").Replace("В-78", "В78"); + // Ауд. + worksheet.Cells[row, col].Value = dto.LectureHalls; + + col = 1; + row++; + } + + worksheet.Cells[1, 1, 1, 12].AutoFilter = true; + worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); + + var stream = new MemoryStream(); + await package.SaveAsAsync(stream); + stream.Position = 0; + return File(stream, "application/vnd.ms-excel", "data.xlsx"); + } +} \ No newline at end of file