Merge branch 'dev' into feature/email_notifications

This commit is contained in:
commit 6a483b1de2
16 changed files with 561 additions and 35 deletions

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudApp.Data
{
@ -13,16 +14,7 @@ namespace AsbCloudApp.Data
/// </summary>
public PaginationContainer()
{
Items = new List<T>(4);
}
/// <summary>
/// конструктор
/// </summary>
/// <param name="capacity"></param>
public PaginationContainer(int capacity)
{
Items = new List<T>(capacity);
Items = Enumerable.Empty<T>();
}
/// <summary>
@ -43,6 +35,6 @@ namespace AsbCloudApp.Data
/// <summary>
/// Данные
/// </summary>
public List<T> Items { get; set; }
public IEnumerable<T> Items { get; set; }
}
}

View File

@ -87,5 +87,10 @@ namespace AsbCloudApp.Data.ProcessMap
/// Плановый процент использования spin master
/// </summary>
public double UsageSpin { get; set; }
/// <summary>
/// DTO типа секции
/// </summary>
public WellSectionTypeDto WellSectionType { get; set; } = null!;
}
}

View File

@ -0,0 +1,17 @@
namespace AsbCloudApp.Data;
/// <summary>
/// Тип секции
/// </summary>
public class WellSectionTypeDto : IId
{
/// <summary>
/// Id секции
/// </summary>
public int Id { get; set; }
/// <summary>
/// Название типа секции
/// </summary>
public string Caption { get; set; } = null!;
}

View File

@ -13,11 +13,22 @@ public interface IHelpPageRepository : ICrudRepository<HelpPageDto>
/// <summary>
/// Получение справки по url страницы и id категории
/// </summary>
/// <param name="urlPage"></param>
/// <param name="key"></param>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<HelpPageDto?> GetOrDefaultByUrlPageAndIdCategoryAsync(string urlPage,
Task<HelpPageDto?> GetOrDefaultByUrlPageAndIdCategoryAsync(string key,
int idCategory,
CancellationToken cancellationToken);
/// <summary>
/// Проверяет наличие справки для страницы
/// </summary>
/// <param name="key"></param>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> IsExistingAsync(string key,
int idCategory,
CancellationToken cancellationToken);
}

View File

@ -0,0 +1,35 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services;
/// <summary>
/// Сервис импорта/экспорта для РТК вводимых вручную
/// </summary>
public interface IProcessMapPlanImportService
{
/// <summary>
/// Загрузить данные из файла
/// </summary>
/// <param name="idWell"></param>
/// <param name="idUser"></param>
/// <param name="stream"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task ImportAsync(int idWell, int idUser, Stream stream, CancellationToken cancellationToken);
/// <summary>
/// Сформировать файл с данными
/// </summary>
/// <param name="idWell"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Stream> ExportAsync(int idWell, CancellationToken cancellationToken);
/// <summary>
/// Получение шаблона для заполнения
/// </summary>
/// <returns></returns>
Task<Stream> GetExcelTemplateStreamAsync(CancellationToken cancellationToken);
}

View File

@ -35,6 +35,7 @@
<EmbeddedResource Include="Services\ProcessMap\ProcessMapReportTemplate.xlsx" />
<EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" />
<EmbeddedResource Include="Services\WellOperationService\WellOperationImportTemplate.xlsx" />
<EmbeddedResource Include="Services\ProcessMap\ProcessMapPlanTemplate.xlsx" />
</ItemGroup>
<ItemGroup>

View File

@ -127,6 +127,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<ITimezoneService, TimezoneService>();
services.AddTransient<IWellService, WellService>();
services.AddTransient<IWellOperationImportService, WellOperationImportService>();
services.AddTransient<IProcessMapPlanImportService, ProcessMapPlanImportService>();
services.AddTransient<IPlannedTrajectoryImportService, PlannedTrajectoryImportService>();
services.AddTransient<IWellOperationRepository, WellOperationRepository>();
services.AddTransient<IScheduleReportService, ScheduleReportService>();
@ -194,6 +195,8 @@ namespace AsbCloudInfrastructure
services.AddTransient<ITrajectoryFactRepository, TrajectoryFactRepository>();
services.AddTransient<IFaqRepository, FaqRepository>();
services.AddTransient<IWellContactService, WellContactService>();
services.AddTransient<ICrudRepository<WellSectionTypeDto>, CrudCacheRepositoryBase<WellSectionTypeDto,
WellSectionType>>();
// Subsystem service
services.AddTransient<ICrudRepository<SubsystemDto>, CrudCacheRepositoryBase<SubsystemDto, Subsystem>>();

View File

@ -111,7 +111,7 @@ namespace AsbCloudInfrastructure.Repository
.ToListAsync(token)
.ConfigureAwait(false);
result.Items = entities.Select(e => Convert(e)).ToList();
result.Items = entities.Select(e => Convert(e));
return result;
}

View File

@ -16,13 +16,13 @@ public class HelpPageRepository : CrudRepositoryBase<HelpPageDto, HelpPage>,
{
}
public async Task<HelpPageDto?> GetOrDefaultByUrlPageAndIdCategoryAsync(string urlPage,
public async Task<HelpPageDto?> GetOrDefaultByUrlPageAndIdCategoryAsync(string key,
int idCategory,
CancellationToken cancellationToken)
{
var helpPage = await dbSet.AsNoTracking()
.SingleOrDefaultAsync(x =>
x.UrlPage == urlPage &&
x.UrlPage == key &&
x.IdCategory == idCategory,
cancellationToken);
@ -31,4 +31,9 @@ public class HelpPageRepository : CrudRepositoryBase<HelpPageDto, HelpPage>,
return helpPage.Adapt<HelpPageDto>();
}
public Task<bool> IsExistingAsync(string key, int idCategory, CancellationToken cancellationToken) =>
dbContext.HelpPages.AnyAsync(h => h.UrlPage == key &&
h.IdCategory == idCategory,
cancellationToken);
}

View File

@ -70,14 +70,14 @@ public class NotificationRepository : CrudCacheRepositoryBase<NotificationDto, N
if (result.Count < skip)
return result;
result.Items = await query
.SortBy(request.SortFields)
.Skip(skip)
.Take(take)
.AsNoTracking()
.Select(x => x.Adapt<NotificationDto>())
.ToListAsync(cancellationToken);
.ToArrayAsync(cancellationToken);
return result;
}

View File

@ -165,7 +165,7 @@ namespace AsbCloudInfrastructure.Repository
.Skip(result.Skip)
.Take(result.Take);
result.Items = await query.ToListAsync(token);
result.Items = await query.ToArrayAsync(token);
return result;
}

View File

@ -0,0 +1,352 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using ClosedXML.Excel;
using System;
using AsbCloudApp.Data;
namespace AsbCloudInfrastructure.Services.ProcessMap;
/*
* password for ProcessMapImportTemplate.xlsx is ASB2020!
*/
public class ProcessMapPlanImportService : IProcessMapPlanImportService
{
private readonly IProcessMapPlanRepository processMapPlanRepository;
private readonly ICrudRepository<WellSectionTypeDto> wellSectionTypeRepository;
private const string sheetNamePlan = "План";
private const int headerRowsCount = 2;
private const int columnWellSectionType = 1;
private const int columnMode = 2;
private const int columnDepthStart = 3;
private const int columnDepthEnd = 4;
private const int columnPressurePlan = 5;
private const int columnPressureLimitMax = 6;
private const int columnAxialLoadPlan = 7;
private const int columnAxialLoadLimitMax = 8;
private const int columnTopDriveTorquePlan = 9;
private const int columnTopDriveTorqueLimitMax = 10;
private const int columnTopDriveSpeedPlan = 11;
private const int columnTopDriveSpeedLimitMax = 12;
private const int columnFlowPlan = 13;
private const int columnFlowLimitMax = 14;
private const int columnRopPlan = 15;
private const int columnUsageSaub = 16;
private const int columnUsageSpin = 17;
private WellSectionTypeDto[] sections = null!;
public ProcessMapPlanImportService(IProcessMapPlanRepository processMapPlanRepository,
ICrudRepository<WellSectionTypeDto> wellSectionTypeRepository)
{
this.processMapPlanRepository = processMapPlanRepository;
this.wellSectionTypeRepository = wellSectionTypeRepository;
}
public async Task ImportAsync(int idWell, int idUser, Stream stream, CancellationToken cancellationToken)
{
sections = (await wellSectionTypeRepository.GetAllAsync(cancellationToken)).ToArray();
using var workBook = new XLWorkbook(stream);
var processPlanMaps = ParseWorkBook(workBook);
foreach (var processPlanMap in processPlanMaps)
{
processPlanMap.IdWell = idWell;
processPlanMap.IdUser = idUser;
}
await processMapPlanRepository.InsertRangeAsync(processPlanMaps, cancellationToken);
}
public async Task<Stream> ExportAsync(int idWell, CancellationToken cancellationToken)
{
var processMapPlans = (await processMapPlanRepository.GetByIdWellAsync(idWell,
cancellationToken)).ToArray();
return await GenerateExcelFileStreamAsync(processMapPlans,
cancellationToken);
}
public async Task<Stream> GetExcelTemplateStreamAsync(CancellationToken cancellationToken)
{
var resourceName = Assembly.GetExecutingAssembly()
.GetManifestResourceNames()
.FirstOrDefault(n => n.EndsWith("ProcessMapPlanTemplate.xlsx"))!;
using var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream(resourceName)!;
var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream, cancellationToken);
memoryStream.Position = 0;
return memoryStream;
}
private void AddToWorkbook(XLWorkbook workbook, ProcessMapPlanDto[] processMapPlans)
{
if (!processMapPlans.Any())
return;
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlan)
?? throw new FileFormatException($"Книга excel не содержит листа {sheetNamePlan}.");
AddToSheet(sheet, processMapPlans);
}
private void AddToSheet(IXLWorksheet sheet, ProcessMapPlanDto[] processMapPlans)
{
for (int i = 0; i < processMapPlans.Length; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
AddToRow(row, processMapPlans[i]);
}
}
private void AddToRow(IXLRow row, ProcessMapPlanDto processMap)
{
row.Cell(columnWellSectionType).Value = processMap.WellSectionType.Caption;
row.Cell(columnMode).Value = GetModeCaption(processMap.IdMode);
row.Cell(columnDepthStart).Value = processMap.DepthStart;
row.Cell(columnDepthEnd).Value = processMap.DepthEnd;
row.Cell(columnPressurePlan).Value = processMap.Pressure.Plan;
row.Cell(columnPressureLimitMax).Value = processMap.Pressure.LimitMax;
row.Cell(columnAxialLoadPlan).Value = processMap.AxialLoad.Plan;
row.Cell(columnAxialLoadLimitMax).Value = processMap.AxialLoad.LimitMax;
row.Cell(columnTopDriveTorquePlan).Value = processMap.TopDriveTorque.Plan;
row.Cell(columnTopDriveTorqueLimitMax).Value = processMap.TopDriveTorque.LimitMax;
row.Cell(columnTopDriveSpeedPlan).Value = processMap.TopDriveSpeed.Plan;
row.Cell(columnTopDriveSpeedLimitMax).Value = processMap.TopDriveSpeed.LimitMax;
row.Cell(columnFlowPlan).Value = processMap.Flow.Plan;
row.Cell(columnFlowLimitMax).Value = processMap.Flow.LimitMax;
row.Cell(columnRopPlan).Value = processMap.RopPlan;
row.Cell(columnUsageSaub).Value = processMap.UsageSaub;
row.Cell(columnUsageSpin).Value = processMap.UsageSpin;
}
private ProcessMapPlanDto[] ParseWorkBook(IXLWorkbook workbook)
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlan)
?? throw new FileFormatException($"Книга excel не содержит листа {sheetNamePlan}.");
return ParseSheet(sheet);
}
private ProcessMapPlanDto[] ParseSheet(IXLWorksheet sheet)
{
const int columnsCount = 17;
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnsCount)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
var rowsCount = sheet.RowsUsed().Count() - headerRowsCount;
if (rowsCount <= 0)
return Array.Empty<ProcessMapPlanDto>();
var processMapPlans = new ProcessMapPlanDto[rowsCount];
var parseErrors = new List<string>();
for (int i = 0; i < processMapPlans.Length; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
try
{
processMapPlans[i] = ParseRow(row);
}
catch (FileFormatException ex)
{
parseErrors.Add(ex.Message);
}
}
if (parseErrors.Any())
throw new FileFormatException(string.Join("\r\n", parseErrors));
return processMapPlans;
}
private ProcessMapPlanDto ParseRow(IXLRow row)
{
var wellSectionTypeCaption = GetCellValue<string>(row, columnWellSectionType).Trim().ToLower();
var modeName = GetCellValue<string>(row, columnMode).Trim().ToLower();
var depthStart = GetCellValue<double>(row, columnDepthStart);
var depthEnd = GetCellValue<double>(row, columnDepthEnd);
var pressurePlan = GetCellValue<double>(row, columnPressurePlan);
var pressureLimitMax = GetCellValue<double>(row, columnPressureLimitMax);
var axialLoadPlan = GetCellValue<double>(row, columnAxialLoadPlan);
var axialLoadLimitMax = GetCellValue<double>(row, columnAxialLoadLimitMax);
var topDriveTorquePlan = GetCellValue<double>(row, columnTopDriveTorquePlan);
var topDriveTorqueLimitMax = GetCellValue<double>(row, columnTopDriveTorqueLimitMax);
var topDriveSpeedPlan = GetCellValue<double>(row, columnTopDriveSpeedPlan);
var topDriveSpeedLimitMax = GetCellValue<double>(row, columnTopDriveSpeedLimitMax);
var flowPlan = GetCellValue<double>(row, columnFlowPlan);
var flowLimitMax = GetCellValue<double>(row, columnFlowLimitMax);
var ropPlan = GetCellValue<double>(row, columnRopPlan);
var usageSaub = GetCellValue<double>(row, columnUsageSaub);
var usageSpin = GetCellValue<double>(row, columnUsageSpin);
var wellSection = sections.FirstOrDefault(s => s.Caption.Trim().ToLower() == wellSectionTypeCaption)
?? throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указана некорректная секция");
var idMode = GetIdMode(modeName)
?? throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указан некорректный режим");
if (depthStart is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указана некорректная стартовая глубина");
if (depthEnd is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указана некорректная конечная глубина");
if (pressurePlan is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное плановое значение перепада давления");
if (pressureLimitMax is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное ограничение перепада давления");
if (axialLoadPlan is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное плановое значение нагрузки");
if (axialLoadLimitMax is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное ограничение нагрузки");
if (topDriveTorquePlan is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное плановое значение момента на ВСП");
if (topDriveTorqueLimitMax is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное ограничение момента на ВСП");
if (topDriveSpeedPlan is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное плановое значение оборотов на ВСП");
if (topDriveSpeedLimitMax is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное ограничения оборота на ВСП");
if (flowPlan is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное плановое значение расхода");
if (flowLimitMax is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное ограничение расхода");
if (ropPlan is < 0 or > 50000)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указано некорректное плановое значение механической скорости");
if (usageSaub is < 0 or > 100)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указан некорректный плановый процент использования АКБ");
if (usageSpin is < 0 or > 100)
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. В строке {row.RowNumber()} указан некорректные плановый процент использования spin master");
return new()
{
IdWellSectionType = wellSection.Id,
IdMode = idMode,
DepthStart = depthStart,
LastUpdate = DateTime.UtcNow,
DepthEnd = depthEnd,
Pressure = new()
{
Plan = pressurePlan,
LimitMax = pressureLimitMax
},
AxialLoad = new()
{
Plan = axialLoadPlan,
LimitMax = axialLoadLimitMax
},
TopDriveTorque = new()
{
Plan = topDriveTorquePlan,
LimitMax = topDriveTorqueLimitMax
},
TopDriveSpeed = new()
{
Plan = topDriveSpeedPlan,
LimitMax = topDriveSpeedLimitMax
},
Flow = new()
{
Plan = flowPlan,
LimitMax = flowLimitMax
},
RopPlan = ropPlan,
UsageSaub = usageSaub,
UsageSpin = usageSpin
};
}
private async Task<Stream> GenerateExcelFileStreamAsync(ProcessMapPlanDto[] processMapPlans,
CancellationToken cancellationToken)
{
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
AddToWorkbook(workbook, processMapPlans);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private static int? GetIdMode(string modeName) =>
modeName switch
{
"ручной" => 0,
"ротор" => 1,
"слайд" => 2,
_ => null
};
private static string GetModeCaption(int idMode)
=> idMode switch
{
1 => "Ротор",
2 => "Слайд",
_ => "Ручной",
};
private static T GetCellValue<T>(IXLRow row, int columnNumber)
{
var cell = row.Cell(columnNumber);
if (cell.Value is T cellValue)
{
return cellValue;
}
throw new FileFormatException(
$"Лист {row.Worksheet.Name}. Ячейка:{columnNumber},{row.RowNumber()} содержит некорректное значение");
}
}

View File

@ -101,6 +101,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
var eventsDict = events.ToDictionary(x=>x.IdEvent, x => x);
var usersDict = users.ToDictionary(x => x.IdUser, x => x);
var messagesDtoList = new List<MessageDto>();
foreach (var message in messagesList)
{
var messageDto = new MessageDto
@ -126,10 +128,11 @@ namespace AsbCloudInfrastructure.Services.SAUB
messageDto.CategoryId = e.IdCategory;
messageDto.Message = e.MakeMessageText(message);
}
result.Items.Add(messageDto);
messagesDtoList.Add(messageDto);
}
result.Items = result.Items.Concat(messagesDtoList);
return result;
}

View File

@ -21,18 +21,21 @@ public class HelpPageController : ControllerBase
{
private readonly IHelpPageService helpPageService;
private readonly IUserRepository userRepository;
private readonly IHelpPageRepository helpPageRepository;
public HelpPageController(IHelpPageService helpPageService,
IUserRepository userRepository)
IUserRepository userRepository,
IHelpPageRepository helpPageRepository)
{
this.helpPageService = helpPageService;
this.userRepository = userRepository;
this.helpPageRepository = helpPageRepository;
}
/// <summary>
/// Загрузка файла справки
/// </summary>
/// <param name="urlPage">Url страницы</param>
/// <param name="key">Ключ страницы</param>
/// <param name="idCategory">Id категории файла. Допустимое значение параметра: 20000</param>
/// <param name="file">Файл справки</param>
/// <param name="cancellationToken">Токен для отмены задачи</param>
@ -41,7 +44,7 @@ public class HelpPageController : ControllerBase
[Permission]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
public async Task<IActionResult> UploadAsync(
string urlPage,
[Required] string key,
[Range(minimum: 20000, maximum: 20000, ErrorMessage = "Категория файла недопустима. Допустимые: 20000")]
int idCategory,
[Required] IFormFile file,
@ -57,7 +60,7 @@ public class HelpPageController : ControllerBase
using var fileStream = file.OpenReadStream();
int helpPageId = await helpPageService.AddOrUpdateAsync(urlPage,
int helpPageId = await helpPageService.AddOrUpdateAsync(key,
idCategory,
file.FileName,
fileStream,
@ -69,19 +72,20 @@ public class HelpPageController : ControllerBase
/// <summary>
/// Получение файла справки
/// </summary>
/// <param name="urlPage">Url страницы</param>
/// <param name="key">Ключ страницы</param>
/// <param name="idCategory">Id категории файла. Допустимое значение параметра: 20000</param>
/// <param name="cancellationToken">Токен для отмены задачи</param>
/// <returns></returns>
[HttpGet]
[Route("{urlPage}/{idCategory}")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> GetFileAsync(string urlPage,
int idCategory,
public async Task<IActionResult> GetFileAsync(
[Required] string key,
[Range(minimum: 20000, maximum: 20000, ErrorMessage = "Категория файла недопустима. Допустимые: 20000")]
int idCategory,
CancellationToken cancellationToken)
{
var file = await helpPageService.GetFileStreamAsync(urlPage,
var file = await helpPageService.GetFileStreamAsync(key,
idCategory,
cancellationToken);
@ -94,4 +98,27 @@ public class HelpPageController : ControllerBase
return File(memoryStream, "application/pdf", file.fileName);
}
/// <summary>
/// Проверяет наличие справки для страницы
/// </summary>
/// <param name="key">Ключ страницы</param>
/// <param name="idCategory">Id категории файла. Допустимое значение параметра: 20000</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet]
[Route("isExisting")]
[ProducesResponseType(typeof(bool), (int)HttpStatusCode.OK)]
public async Task<IActionResult> IsExistingAsync(
[Required] string key,
[Range(minimum: 20000, maximum: 20000, ErrorMessage = "Категория файла недопустима. Допустимые: 20000")]
int idCategory,
CancellationToken cancellationToken)
{
var helpPage = await helpPageRepository.GetOrDefaultByUrlPageAndIdCategoryAsync(key,
idCategory,
cancellationToken);
return Ok(helpPage != null);
}
}

View File

@ -7,9 +7,12 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace AsbCloudWebApi.Controllers
{
@ -25,6 +28,7 @@ namespace AsbCloudWebApi.Controllers
private readonly IHubContext<TelemetryHub> telemetryHubContext;
private readonly IProcessMapReportMakerService processMapReportService;
private readonly IProcessMapReportService processMapService;
private readonly IProcessMapPlanImportService processMapPlanImportService;
private const string SirnalRMethodGetDataName = "UpdateProcessMap";
@ -34,13 +38,15 @@ namespace AsbCloudWebApi.Controllers
IProcessMapReportMakerService processMapReportService,
IProcessMapReportService processMapService,
ITelemetryService telemetryService,
IHubContext<TelemetryHub> telemetryHubContext)
IHubContext<TelemetryHub> telemetryHubContext,
IProcessMapPlanImportService processMapPlanImportService)
: base(wellService, repository)
{
this.telemetryService = telemetryService;
this.telemetryHubContext = telemetryHubContext;
this.processMapReportService = processMapReportService;
this.processMapService = processMapService;
this.processMapPlanImportService = processMapPlanImportService;
}
@ -61,7 +67,6 @@ namespace AsbCloudWebApi.Controllers
var idWell = telemetryService.GetIdWellByTelemetryUid(uid);
if (idWell is null)
return BadRequest($"Wrong uid {uid}");
#warning implement Process map get method
return Ok(Enumerable.Empty<ProcessMapPlanDto>());
}
@ -94,7 +99,6 @@ namespace AsbCloudWebApi.Controllers
/// <param name="wellId"></param>
/// /// <param name="token"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[HttpGet]
[Route("getReportFile/{wellId}")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
@ -132,7 +136,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Добавить запись
/// Добавить запись плановой РТК
/// </summary>
/// <param name="value"></param>
/// <param name="token"></param>
@ -147,7 +151,7 @@ namespace AsbCloudWebApi.Controllers
}
/// <summary>
/// Редактировать запись по id
/// Редактировать запись по id плановой РТК
/// </summary>
/// <param name="value">запись</param>
/// <param name="token"></param>
@ -161,6 +165,77 @@ namespace AsbCloudWebApi.Controllers
return result;
}
/// <summary>
/// Возвращает шаблон файла импорта плановой РТК
/// </summary>
/// <returns>Запрашиваемый файл</returns>
[HttpGet]
[Route("template")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetTemplateAsync(CancellationToken cancellationToken)
{
var stream = await processMapPlanImportService.GetExcelTemplateStreamAsync(cancellationToken);
var fileName = "ЕЦП_шаблон_файла_РТК.xlsx";
return File(stream, "application/octet-stream", fileName);
}
/// <summary>
/// Импортирует плановой РТК из excel (xlsx) файла
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="file">Загружаемый файл</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
[Route("import")]
public async Task<IActionResult> ImportAsync(int idWell,
[Required] IFormFile file,
CancellationToken cancellationToken)
{
int? idUser = User.GetUserId();
if (idUser is null)
return Forbid();
if (Path.GetExtension(file.FileName).ToLower() != ".xlsx")
return BadRequest("Требуется xlsx файл.");
using Stream stream = file.OpenReadStream();
await processMapPlanImportService.ImportAsync(idWell,
idUser.Value,
stream,
cancellationToken);
return Ok();
}
/// <summary>
/// Экспорт плановой РТК в excel
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet]
[Route("export")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> ExportAsync([FromQuery] int idWell, CancellationToken cancellationToken)
{
int? idUser = User.GetUserId();
if (idUser is null)
return Forbid();
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken);
if (well is null)
return NoContent();
var stream = await processMapPlanImportService.ExportAsync(idWell, cancellationToken);
var fileName = $"РТК-план по скважине {well.Caption} куст {well.Cluster}.xlsx";
return File(stream, "application/octet-stream", fileName);
}
private async Task NotifyUsersBySignalR(int idWell, CancellationToken token)
{
var dtos = await service.GetAllAsync(idWell, null, token);