feat: add parsing from files
Some checks failed
.NET Test Pipeline / build-and-test (push) Failing after 49s
Build and Deploy Docker Container / build-and-deploy (push) Successful in 1m42s

This commit is contained in:
2025-02-03 03:44:40 +03:00
parent dc08285ec8
commit 885b937b0b
3 changed files with 319 additions and 28 deletions

View File

@ -1,6 +1,8 @@
using Asp.Versioning;
using Cronos;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Mirea.Api.DataAccess.Persistence;
@ -11,15 +13,19 @@ using Mirea.Api.Endpoint.Common.MapperDto;
using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Configuration.Model;
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
using Mirea.Api.Endpoint.Sync;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Mirea.Api.Endpoint.Controllers.V1.Configuration;
[ApiVersion("1.0")]
public class ScheduleController(ILogger<ScheduleController> logger, IOptionsSnapshot<GeneralConfig> config, UberDbContext dbContext) : ConfigurationBaseController
public class ScheduleController(ILogger<ScheduleController> logger, IOptionsSnapshot<GeneralConfig> config, UberDbContext dbContext, IServiceProvider provider) : ConfigurationBaseController
{
/// <summary>
/// Retrieves the cron update schedule and calculates the next scheduled tasks based on the provided depth.
@ -113,7 +119,7 @@ public class ScheduleController(ILogger<ScheduleController> logger, IOptionsSnap
return generalConfig.ScheduleSettings!.CronUpdateSkipDateList
.ConvertToDto();
}
/// <summary>
/// Updates the list of cron update skip dates in the configuration.
@ -139,4 +145,62 @@ public class ScheduleController(ILogger<ScheduleController> logger, IOptionsSnap
return Ok();
}
/// <summary>
/// Uploads schedule files and initiates synchronization.
/// </summary>
/// <param name="files">The list of schedule files to upload.</param>
/// <param name="defaultCampus">The default campus for each uploaded file. Must match the number of files.</param>
/// <param name="force">If true, removes all existing lessons before synchronization. Default is false.</param>
/// <returns>Success or failure.</returns>
/// <exception cref="ControllerArgumentException">
/// Thrown if:
/// - No files are provided.
/// - The number of default campuses does not match the number of files.
/// - Any default campus is null or empty.
/// </exception>
[HttpPost("Upload")]
public async Task<ActionResult> UploadScheduleFiles(List<IFormFile>? files, [FromQuery] string[]? defaultCampus, [FromQuery] bool force = false)
{
if (files == null || files.Count == 0)
throw new ControllerArgumentException("No files were found.");
if (defaultCampus == null || files.Count != defaultCampus.Length)
throw new ControllerArgumentException("No default campuses are specified for the file.");
if (defaultCampus.Any(string.IsNullOrEmpty))
throw new ControllerArgumentException("Each file should have a default campus.");
var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));
if (!Directory.Exists(tempDirectory))
Directory.CreateDirectory(tempDirectory);
List<(string, string)> filePaths = [];
for (var i = 0; i < files.Count; i++)
{
if (files[i].Length <= 0)
continue;
var filePath = Path.Combine(tempDirectory, files[i].FileName);
await using var stream = new FileStream(filePath, FileMode.Create);
await files[i].CopyToAsync(stream);
filePaths.Add((filePath, defaultCampus[i]));
}
var sync = (ScheduleSynchronizer)ActivatorUtilities.GetServiceOrCreateInstance(provider, typeof(ScheduleSynchronizer));
if (force)
{
dbContext.Lessons.RemoveRange(dbContext.Lessons.ToList());
await dbContext.SaveChangesAsync();
}
_ = sync.StartSync(filePaths, CancellationToken.None);
return Ok();
}
}