using System; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Data.DailyReport; using AsbCloudApp.Data.DailyReport.Blocks.Sign; using AsbCloudApp.Data.DailyReport.Blocks.Subsystems; using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance; using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.DailyReport; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace AsbCloudWebApi.Controllers; /// <summary> /// Суточный отчёт /// </summary> [ApiController] [Route("api/well/{idWell:int}/[controller]")] [Authorize] public class DailyReportController : ControllerBase { private readonly IWellOperationRepository wellOperationRepository; private readonly IDailyReportService dailyReportService; private readonly IDailyReportExportService dailyReportExportService; private readonly IWellService wellService; public DailyReportController(IWellOperationRepository wellOperationRepository, IDailyReportService dailyReportService, IDailyReportExportService dailyReportExportService, IWellService wellService) { this.wellOperationRepository = wellOperationRepository; this.dailyReportService = dailyReportService; this.dailyReportExportService = dailyReportExportService; this.wellService = wellService; } private int IdUser { get { var idUser = User.GetUserId(); if (!idUser.HasValue) throw new ForbidException("Неизвестный пользователь"); return idUser.Value; } } /// <summary> /// Обновить подпись /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="dateDailyReport">Дата суточного отчёта</param> /// <param name="signBlock">Обновляемый блок</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpPut("sign")] [Permission] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public Task<IActionResult> UpdateSignBlockAsync(int idWell, DateOnly dateDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) => UpdateOrInsertAsync(idWell, dateDailyReport, signBlock, cancellationToken); /// <summary> /// Обновить наработку подсистем /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="dateDailyReport">Дата суточного отчёта</param> /// <param name="subsystemBlock">Обновляемый блок</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpPut("subsystem")] [Permission] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, DateOnly dateDailyReport, SubsystemBlockDto subsystemBlock, CancellationToken cancellationToken) { var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" }; if (subsystemBlock.Subsystems.Any(m => !validSubsystemNames.Contains(m.Name))) throw new ArgumentInvalidException($"Возможно добавить подсистемы с именами {string.Join(", ", validSubsystemNames)}", nameof(subsystemBlock.Subsystems)); return UpdateOrInsertAsync(idWell, dateDailyReport, subsystemBlock, cancellationToken); } /// <summary> /// Обновить баланс времени /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="dateDailyReport">Дата суточного отчёта</param> /// <param name="timeBalanceBlock">Обновляемый блок</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpPut("timeBalance")] [Permission] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, DateOnly dateDailyReport, TimeBalanceBlockDto timeBalanceBlock, CancellationToken cancellationToken) { var validWellOperationsIds = new[] { 1, 2, 3, 4 }; if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation))) throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(", ", validWellOperationsIds)}", nameof(timeBalanceBlock.WellOperations)); var wellSections = wellOperationRepository.GetSectionTypes(); if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection)) throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection)); return UpdateOrInsertAsync(idWell, dateDailyReport, timeBalanceBlock, cancellationToken); } /// <summary> /// Получить список суточных отчётов по скважине /// </summary> /// <param name="idWell">Идентификатор скважины</param> /// <param name="request">Параметры запроса</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpGet] [ProducesResponseType(typeof(PaginationContainer<DailyReportDto>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task<IActionResult> GetAsync(int idWell, [FromQuery] FileReportRequest request, CancellationToken cancellationToken) { await AssertUserAccessToWell(idWell, cancellationToken); var dailyReports = await dailyReportService.GetAsync(idWell, request, cancellationToken); return Ok(dailyReports); } /// <summary> /// Получить диапазон дат по которым возможно сформировать суточный отчёты /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpGet("datesRange")] [ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)] public async Task<IActionResult> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken) { await AssertUserAccessToWell(idWell, cancellationToken); var datesRanges = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken); return Ok(datesRanges); } /// <summary> /// Экспорт суточного рапорта /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="dateDailyReport">Дата формирования суточного отчёта</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpGet("{dateDailyReport}")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task<IActionResult> ExportAsync(int idWell, DateOnly dateDailyReport, CancellationToken cancellationToken) { await AssertUserAccessToWell(idWell, cancellationToken); var dailyReport = await dailyReportExportService.ExportAsync(idWell, dateDailyReport, cancellationToken); return File(dailyReport.File, "application/octet-stream", dailyReport.FileName); } private async Task<IActionResult> UpdateOrInsertAsync<TBlock>(int idWell, DateOnly dateDailyReport, TBlock block, CancellationToken cancellationToken) where TBlock : ItemInfoDto { await AssertUserAccessToWell(idWell, cancellationToken); var id = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, IdUser, block, cancellationToken); return Ok(id); } private async Task AssertUserAccessToWell(int idWell, CancellationToken cancellationToken) { var idCompany = User.GetCompanyId(); if (!idCompany.HasValue || !await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken)) throw new ForbidException("Нет доступа к скважине"); } }