forked from ddrilling/AsbCloudServer
Доработки
1. Добавлен шаблон суточного отчёта 2. Рефакторинг DTO для суточного отчёта 3. Обновлена валидация входных данных в методах контроллера 4. Небольшой рефакторинг сервисов
This commit is contained in:
parent
af5d713fc7
commit
dcaec8b4a2
@ -6,11 +6,9 @@ namespace AsbCloudApp.Data.DailyReport.Blocks;
|
|||||||
public class ProcessMapWellDrillingRecordDto
|
public class ProcessMapWellDrillingRecordDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id режима бурения
|
/// Режим бурения
|
||||||
/// 1 - ротор
|
|
||||||
/// 2 - слайд
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int IdMode { get; set; }
|
public string DrillingMode { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Мех. скорость
|
/// Мех. скорость
|
||||||
|
@ -8,15 +8,9 @@ namespace AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
|
|||||||
public class SubsystemRecordDto
|
public class SubsystemRecordDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 1 - АПД, ч/м
|
/// Название подсистемы
|
||||||
/// 11 - АПД ротор
|
|
||||||
/// 12 - АПД слайд
|
|
||||||
/// 65536 - Осцилляция
|
|
||||||
/// 65537 - Демпфер
|
|
||||||
/// 100000 - Автопроработка
|
|
||||||
/// 100001 - АвтоСПО
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int IdSubsystem { get; set; }
|
public string SubsystemName { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Идентификатор временного интервала
|
/// Идентификатор временного интервала
|
||||||
|
@ -15,6 +15,11 @@ public class TimeBalanceBlockDto : EditableBlock
|
|||||||
[Range(1, int.MaxValue)]
|
[Range(1, int.MaxValue)]
|
||||||
public int IdSection { get; set; }
|
public int IdSection { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Название секции
|
||||||
|
/// </summary>
|
||||||
|
public string? SectionName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Плановая проходка скважины
|
/// Плановая проходка скважины
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -6,10 +6,10 @@ namespace AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
|
|||||||
public class TimeBalanceRecordDto
|
public class TimeBalanceRecordDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Мех. бурение - 4001
|
/// Мех. бурение - 1
|
||||||
/// Статический замер - 4002
|
/// Снятие замера, ориентирование - 2
|
||||||
/// Наращивание - 4004
|
/// Наращивание, выход на режим - 3
|
||||||
/// Промывка, ОБР - 4012
|
/// Промывка, проработка - 4
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int IdWellOperation { get; set; }
|
public int IdWellOperation { get; set; }
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ namespace AsbCloudApp.Data.DailyReport.Blocks.WellOperation;
|
|||||||
public class WellOperationRecordDto
|
public class WellOperationRecordDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id категории операции
|
/// Название категории
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? IdWellCategory { get; set; }
|
public string? CategoryName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Продолжительность операции
|
/// Продолжительность операции
|
||||||
|
@ -43,7 +43,7 @@ public class DailyReportExportService : IDailyReportExportService
|
|||||||
private const int columnUseSubsystemPerWellSumDepthInterval = 7;
|
private const int columnUseSubsystemPerWellSumDepthInterval = 7;
|
||||||
private const int columnUseSubsystemPerWellKUsage = 8;
|
private const int columnUseSubsystemPerWellKUsage = 8;
|
||||||
|
|
||||||
private const int columnProcessMapWellDrillingBlockMode = 2;
|
private const int columnProcessMapWellDrillingBlockDrillingMode = 2;
|
||||||
private const int columnProcessMapWellDrillingBlockWellBoreDepth = 3;
|
private const int columnProcessMapWellDrillingBlockWellBoreDepth = 3;
|
||||||
private const int columnProcessMapWellDrillingBlockMechDrillingHours = 4;
|
private const int columnProcessMapWellDrillingBlockMechDrillingHours = 4;
|
||||||
private const int columnProcessMapWellDrillingBlockRopPlan = 5;
|
private const int columnProcessMapWellDrillingBlockRopPlan = 5;
|
||||||
@ -95,12 +95,12 @@ public class DailyReportExportService : IDailyReportExportService
|
|||||||
|
|
||||||
var stream = await GenerateFileAsync(dailyReport, cancellationToken);
|
var stream = await GenerateFileAsync(dailyReport, cancellationToken);
|
||||||
|
|
||||||
var fileName = $"Суточный_отчёт_по_скважине_{dailyReport.WellName}_куст_{dailyReport.Cluster}_от_{dailyReport.DateStart:yy-MM-dd}.xlsx";
|
var fileName = $"Суточный_рапорт_по_скважине_{dailyReport.WellName}_куст_{dailyReport.Cluster}_от_{dailyReport.DateStart:yy-MM-dd}.xlsx";
|
||||||
|
|
||||||
return (fileName, stream);
|
return (fileName, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> GenerateFileAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
|
private static async Task<Stream> GenerateFileAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using var excelTemplateStream = await Assembly
|
using var excelTemplateStream = await Assembly
|
||||||
.GetExecutingAssembly()
|
.GetExecutingAssembly()
|
||||||
@ -172,7 +172,7 @@ public class DailyReportExportService : IDailyReportExportService
|
|||||||
rowCurrent++;
|
rowCurrent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.IdSection;
|
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.SectionName;
|
||||||
sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepthPlan;
|
sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepthPlan;
|
||||||
sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepthFact;
|
sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepthFact;
|
||||||
sheet.Cell(cellTimeBalanceBlockCountWellOperationSlipsTime).Value = timeBalanceBlock.CountWellOperationSlipsTime;
|
sheet.Cell(cellTimeBalanceBlockCountWellOperationSlipsTime).Value = timeBalanceBlock.CountWellOperationSlipsTime;
|
||||||
@ -180,8 +180,8 @@ public class DailyReportExportService : IDailyReportExportService
|
|||||||
|
|
||||||
private static void AddSubsystemBlockToSheet(IXLWorksheet sheet, SubsystemBlockDto subsystemBlock)
|
private static void AddSubsystemBlockToSheet(IXLWorksheet sheet, SubsystemBlockDto subsystemBlock)
|
||||||
{
|
{
|
||||||
var groupedModules = subsystemBlock.Modules.OrderBy(m => m.IdSubsystem)
|
var groupedModules = subsystemBlock.Modules.OrderBy(m => m.SubsystemName)
|
||||||
.GroupBy(m => m.IdSubsystem);
|
.GroupBy(m => m.SubsystemName);
|
||||||
|
|
||||||
var rowСurrent = rowStartSubsystemBlock;
|
var rowСurrent = rowStartSubsystemBlock;
|
||||||
|
|
||||||
@ -228,9 +228,9 @@ public class DailyReportExportService : IDailyReportExportService
|
|||||||
{
|
{
|
||||||
var rowCurrent = rowStartProcessMapWellDrillingBlock;
|
var rowCurrent = rowStartProcessMapWellDrillingBlock;
|
||||||
|
|
||||||
foreach (var processMapWellDrilling in processMapWellDrillingBlock.OrderBy(p => p.IdMode))
|
foreach (var processMapWellDrilling in processMapWellDrillingBlock.OrderBy(p => p.DrillingMode))
|
||||||
{
|
{
|
||||||
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMode).Value = processMapWellDrilling.IdMode;
|
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockDrillingMode).Value = processMapWellDrilling.DrillingMode;
|
||||||
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockWellBoreDepth).Value = processMapWellDrilling.WellBoreDepth;
|
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockWellBoreDepth).Value = processMapWellDrilling.WellBoreDepth;
|
||||||
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMechDrillingHours).Value = processMapWellDrilling.MechDrillingHours;
|
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMechDrillingHours).Value = processMapWellDrilling.MechDrillingHours;
|
||||||
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopPlan).Value = processMapWellDrilling.Rop.Plan;
|
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopPlan).Value = processMapWellDrilling.Rop.Plan;
|
||||||
@ -244,9 +244,9 @@ public class DailyReportExportService : IDailyReportExportService
|
|||||||
{
|
{
|
||||||
sheet.Cell(cellDurationHoursDrillingPerSection).Value = factWellOperationBlock.DurationHoursDrillingPerSection;
|
sheet.Cell(cellDurationHoursDrillingPerSection).Value = factWellOperationBlock.DurationHoursDrillingPerSection;
|
||||||
|
|
||||||
foreach (var factOperation in factWellOperationBlock.WellOperations.OrderBy(w => w.IdWellCategory))
|
foreach (var factOperation in factWellOperationBlock.WellOperations.OrderBy(w => w.CategoryName))
|
||||||
{
|
{
|
||||||
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationCategory).Value = factOperation.IdWellCategory;
|
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationCategory).Value = factOperation.CategoryName;
|
||||||
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationDurationHours).Value = factOperation.DurationHours;
|
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationDurationHours).Value = factOperation.DurationHours;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,8 +115,12 @@ public class DailyReportService : IDailyReportService
|
|||||||
dailyReport.Deposit = well.Deposit;
|
dailyReport.Deposit = well.Deposit;
|
||||||
dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption;
|
dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption;
|
||||||
dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption;
|
dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption;
|
||||||
|
|
||||||
|
if (factWellOperations.Any())
|
||||||
|
{
|
||||||
dailyReport.DepthStart = factWellOperations.Min(o => o.DepthStart);
|
dailyReport.DepthStart = factWellOperations.Min(o => o.DepthStart);
|
||||||
dailyReport.DepthEnd = factWellOperations.Max(o => o.DepthEnd);
|
dailyReport.DepthEnd = factWellOperations.Max(o => o.DepthEnd);
|
||||||
|
}
|
||||||
|
|
||||||
await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken);
|
await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken);
|
||||||
await UpdateSubsystemBlockAsync(dailyReport, cancellationToken);
|
await UpdateSubsystemBlockAsync(dailyReport, cancellationToken);
|
||||||
@ -239,6 +243,9 @@ public class DailyReportService : IDailyReportService
|
|||||||
|
|
||||||
if (dailyReport.TimeBalanceBlock is not null)
|
if (dailyReport.TimeBalanceBlock is not null)
|
||||||
{
|
{
|
||||||
|
dailyReport.TimeBalanceBlock.SectionName = wellOperationRepository.GetSectionTypes()
|
||||||
|
.FirstOrDefault(s => s.Id == dailyReport.TimeBalanceBlock.IdSection)?.Caption;
|
||||||
|
|
||||||
dailyReport.TimeBalanceBlock.CountWellOperationSlipsTime = (await detectedOperationService.GetAsync(
|
dailyReport.TimeBalanceBlock.CountWellOperationSlipsTime = (await detectedOperationService.GetAsync(
|
||||||
new DetectedOperationRequest
|
new DetectedOperationRequest
|
||||||
{
|
{
|
||||||
@ -333,10 +340,10 @@ public class DailyReportService : IDailyReportService
|
|||||||
cancellationToken)).Where(p => p.DateStart >= dailyReport.DateStart &&
|
cancellationToken)).Where(p => p.DateStart >= dailyReport.DateStart &&
|
||||||
p.DateStart <= dailyReport.DateEnd &&
|
p.DateStart <= dailyReport.DateEnd &&
|
||||||
p.IdMode.HasValue)
|
p.IdMode.HasValue)
|
||||||
.GroupBy(p => p.IdMode)
|
.GroupBy(p => p.DrillingMode)
|
||||||
.Select(g => new ProcessMapWellDrillingRecordDto
|
.Select(g => new ProcessMapWellDrillingRecordDto
|
||||||
{
|
{
|
||||||
IdMode = g.Key!.Value,
|
DrillingMode = g.Key,
|
||||||
WellBoreDepth = g.Sum(p => p.DeltaDepth),
|
WellBoreDepth = g.Sum(p => p.DeltaDepth),
|
||||||
Rop = new PlanFactDto<double?>
|
Rop = new PlanFactDto<double?>
|
||||||
{
|
{
|
||||||
@ -356,7 +363,7 @@ public class DailyReportService : IDailyReportService
|
|||||||
WellOperations = factWellOperations.GroupBy(o => o.IdParentCategory)
|
WellOperations = factWellOperations.GroupBy(o => o.IdParentCategory)
|
||||||
.Select(g => new WellOperationRecordDto
|
.Select(g => new WellOperationRecordDto
|
||||||
{
|
{
|
||||||
IdWellCategory = g.Key,
|
CategoryName = g.First().CategoryName,
|
||||||
DurationHours = g.Sum(o => o.DurationHours)
|
DurationHours = g.Sum(o => o.DurationHours)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
Binary file not shown.
@ -110,7 +110,7 @@ public class DailyReportServiceTest
|
|||||||
{
|
{
|
||||||
new SubsystemRecordDto
|
new SubsystemRecordDto
|
||||||
{
|
{
|
||||||
IdSubsystem = 10000,
|
SubsystemName = "АвтоСПО",
|
||||||
IdTimeInterval = 1,
|
IdTimeInterval = 1,
|
||||||
UsedTimeHours = 24,
|
UsedTimeHours = 24,
|
||||||
SumDepthInterval = 1500,
|
SumDepthInterval = 1500,
|
||||||
|
@ -70,6 +70,13 @@ public class DailyReportController : ControllerBase
|
|||||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
public async Task<IActionResult> InsertAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
|
public async Task<IActionResult> InsertAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var dateStartToDateTime = dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
|
||||||
|
throw new ArgumentInvalidException("Невозможно сформировать суточный отчёт", nameof(dateStart));
|
||||||
|
|
||||||
await AssertUserAccessToWell(idWell, cancellationToken);
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
var id = await dailyReportService.InsertAsync(idWell, dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
|
var id = await dailyReportService.InsertAsync(idWell, dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
|
||||||
@ -90,8 +97,7 @@ public class DailyReportController : ControllerBase
|
|||||||
[Permission]
|
[Permission]
|
||||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
public Task<IActionResult>
|
public Task<IActionResult> UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) =>
|
||||||
UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) =>
|
|
||||||
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken);
|
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -109,10 +115,10 @@ public class DailyReportController : ControllerBase
|
|||||||
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, int idDailyReport, SubsystemBlockDto subsystemBlock,
|
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, int idDailyReport, SubsystemBlockDto subsystemBlock,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var validSubsystemIds = new[] { 100000, 100001 };
|
var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" };
|
||||||
|
|
||||||
if (subsystemBlock.Modules.Any(m => !validSubsystemIds.Contains(m.IdSubsystem)))
|
if (subsystemBlock.Modules.Any(m => !validSubsystemNames.Contains(m.SubsystemName)))
|
||||||
throw new ArgumentInvalidException($"Возможно добавить модули только с Id: {string.Join(", ", validSubsystemIds)}",
|
throw new ArgumentInvalidException($"Возможно добавить модули только с именами {string.Join(", ", validSubsystemNames)}",
|
||||||
nameof(subsystemBlock.Modules));
|
nameof(subsystemBlock.Modules));
|
||||||
|
|
||||||
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
|
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
|
||||||
@ -133,7 +139,7 @@ public class DailyReportController : ControllerBase
|
|||||||
public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, int idDailyReport, TimeBalanceBlockDto timeBalanceBlock,
|
public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, int idDailyReport, TimeBalanceBlockDto timeBalanceBlock,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var validWellOperationsIds = new[] { 4001, 4002, 4004, 4012 };
|
var validWellOperationsIds = new[] { 1, 2, 3, 4 };
|
||||||
|
|
||||||
if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
|
if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
|
||||||
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(", ", validWellOperationsIds)}",
|
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(", ", validWellOperationsIds)}",
|
||||||
@ -187,18 +193,25 @@ public class DailyReportController : ControllerBase
|
|||||||
/// Экспорт суточного рапорта
|
/// Экспорт суточного рапорта
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">Id скважины</param>
|
/// <param name="idWell">Id скважины</param>
|
||||||
/// <param name="dailyReportDateStart">Дата формирования суточного отчёта</param>
|
/// <param name="dateStart">Дата формирования суточного отчёта</param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet("{dailyReportDateStart}")]
|
[HttpGet("{dateStart}")]
|
||||||
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||||
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dailyReportDateStart, CancellationToken cancellationToken)
|
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var dateStartToDateTime = dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
|
||||||
|
|
||||||
|
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
|
||||||
|
throw new ArgumentInvalidException("Невозможно получить суточный отчёт", nameof(dateStart));
|
||||||
|
|
||||||
await AssertUserAccessToWell(idWell, cancellationToken);
|
await AssertUserAccessToWell(idWell, cancellationToken);
|
||||||
|
|
||||||
var dailyReport = await dailyReportExportService.ExportAsync(idWell,
|
var dailyReport = await dailyReportExportService.ExportAsync(idWell,
|
||||||
dailyReportDateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
|
dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
|
||||||
|
|
||||||
return File(dailyReport.File, "application/octet-stream", dailyReport.FileName);
|
return File(dailyReport.File, "application/octet-stream", dailyReport.FileName);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user