From 510595239c89a209873797f254cd77da7fcda2ec Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 24 Mar 2023 19:27:30 +1400 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/DailyReport/ItemInfoDto.cs | 3 +- .../Data/DailyReport/TimeBalanceDto.cs | 3 +- AsbCloudApp/Services/IDailyReportService.cs | 10 -- .../Model/DailyReport/DailyReportInfo.cs | 1 - AsbCloudDb/Model/DailyReport/ItemInfo.cs | 2 +- AsbCloudDb/Model/DailyReport/TimeBalance.cs | 96 ----------- .../DailyReport/DailyReportService.cs | 161 +++++++++--------- .../Controllers/DailyReportController.cs | 58 +++---- 8 files changed, 117 insertions(+), 217 deletions(-) delete mode 100644 AsbCloudDb/Model/DailyReport/TimeBalance.cs diff --git a/AsbCloudApp/Data/DailyReport/ItemInfoDto.cs b/AsbCloudApp/Data/DailyReport/ItemInfoDto.cs index ac27a385..7cfaeed0 100644 --- a/AsbCloudApp/Data/DailyReport/ItemInfoDto.cs +++ b/AsbCloudApp/Data/DailyReport/ItemInfoDto.cs @@ -3,7 +3,8 @@ namespace AsbCloudApp.Data.DailyReport { /// - /// хранение дополнительной информации о записи + /// хранение дополнительной информации о записи + /// автоматическое формирование данных на серверной стороне /// public class ItemInfoDto { diff --git a/AsbCloudApp/Data/DailyReport/TimeBalanceDto.cs b/AsbCloudApp/Data/DailyReport/TimeBalanceDto.cs index 55db7850..efed1ea4 100644 --- a/AsbCloudApp/Data/DailyReport/TimeBalanceDto.cs +++ b/AsbCloudApp/Data/DailyReport/TimeBalanceDto.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace AsbCloudApp.Data.DailyReport { @@ -11,7 +12,7 @@ namespace AsbCloudApp.Data.DailyReport /// /// Статистика по операциям /// - public IEnumerable? OperationsStat { get; set; } + public IEnumerable OperationsStat { get; set; } = Enumerable.Empty(); } } diff --git a/AsbCloudApp/Services/IDailyReportService.cs b/AsbCloudApp/Services/IDailyReportService.cs index 3943e86c..574a04bf 100644 --- a/AsbCloudApp/Services/IDailyReportService.cs +++ b/AsbCloudApp/Services/IDailyReportService.cs @@ -32,16 +32,6 @@ namespace AsbCloudApp.Services /// Task AddAsync(int idWell, DateTime startDate, int idUser, CancellationToken token = default); - /// - /// изменить данные для суточного рапорта - /// - /// - /// - /// - /// - /// - Task UpdateAsync(int idWell, DateTime date, DailyReportDto dto, CancellationToken token = default); - /// /// Сформировать файл рапорта /// diff --git a/AsbCloudDb/Model/DailyReport/DailyReportInfo.cs b/AsbCloudDb/Model/DailyReport/DailyReportInfo.cs index ea8fafe0..d5a7bfd6 100644 --- a/AsbCloudDb/Model/DailyReport/DailyReportInfo.cs +++ b/AsbCloudDb/Model/DailyReport/DailyReportInfo.cs @@ -7,7 +7,6 @@ namespace AsbCloudDb.Model public Head Head { get; set; } = null!; public Bha Bha { get; set; } = new(); public NoDrilling NoDrilling { get; set; } = new(); - public TimeBalance TimeBalance { get; set; } = new(); public Saub Saub { get; set; } = new(); public Sign Sign { get; set; } = new(); } diff --git a/AsbCloudDb/Model/DailyReport/ItemInfo.cs b/AsbCloudDb/Model/DailyReport/ItemInfo.cs index bf579080..3d7e6793 100644 --- a/AsbCloudDb/Model/DailyReport/ItemInfo.cs +++ b/AsbCloudDb/Model/DailyReport/ItemInfo.cs @@ -12,6 +12,6 @@ namespace AsbCloudDb.Model /// /// дата последнего обновления блока /// - public DateTimeOffset? LastUpdateDate { get; set; } + public DateTimeOffset LastUpdateDate { get; set; } = DateTimeOffset.Now; } } diff --git a/AsbCloudDb/Model/DailyReport/TimeBalance.cs b/AsbCloudDb/Model/DailyReport/TimeBalance.cs deleted file mode 100644 index db9a9ffc..00000000 --- a/AsbCloudDb/Model/DailyReport/TimeBalance.cs +++ /dev/null @@ -1,96 +0,0 @@ -namespace AsbCloudDb.Model.DailyReport -{ - public class TimeBalance : ItemInfo - { - /// - /// Бурение - /// - public string Drilling { get; set; } = string.Empty; - - /// - /// Промывка - /// - public string Flushing { get; set; } = string.Empty; - - /// - /// Наращивание - /// - public string Building { get; set; } = string.Empty; - - /// - /// Проработка - /// - public string Elaboration { get; set; } = string.Empty; - - /// - /// Расширка - /// - public string Extension { get; set; } = string.Empty; - - /// - /// Ремонт - /// - public string Repair { get; set; } = string.Empty; - - /// - /// КНБК - /// - public string Knbk { get; set; } = string.Empty; - - /// - /// СПО - /// - public string Spo { get; set; } = string.Empty; - - /// - /// ПЗР - /// - public string Pzr { get; set; } = string.Empty; - - /// - /// ПВО - /// - public string Pvo { get; set; } = string.Empty; - - /// - /// ПГР - /// - public string Pgr { get; set; } = string.Empty; - - /// - /// ГИС - /// - public string Gis { get; set; } = string.Empty; - - /// - /// ОЗЦ - /// - public string Ozc { get; set; } = string.Empty; - - /// - /// Тех. работы - /// - public string EngineeringWorks { get; set; } = string.Empty; - - /// - /// Снятие замера - /// - public string TakingMeasure { get; set; } = string.Empty; - - /// - /// Цементирование - /// - public string Cementing { get; set; } = string.Empty; - - /// - /// Простой - /// - public string Simple { get; set; } = string.Empty; - - /// - /// НПВ - /// - public string Npv { get; set; } = string.Empty; - } -} - diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index 1cc5f2b7..5a814373 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -47,52 +47,41 @@ namespace AsbCloudInfrastructure.Services.DailyReport var query = db.DailyReports.Where(r => r.IdWell == idWell); - DateOnly ExtractDate(DateTime dateTime) - { - var dateTimeOffset = dateTime.ToUtcDateTimeOffset(well!.Timezone.Hours); - var date = new DateOnly(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day); - return date; - } - if (begin is not null) { - var beginDateOnly = ExtractDate(begin.Value); + var beginDateOnly = ExtractDate(begin.Value, well); query = query.Where(d => d.StartDate >= beginDateOnly); } if (end is not null) { - var endDateOnly = ExtractDate(end.Value); + var endDateOnly = ExtractDate(end.Value, well); query = query.Where(d => d.StartDate <= endDateOnly); } - var entities = await query.OrderByDescending(e => e.StartDate).ToListAsync(token); + var entities = await query.OrderByDescending(e => e.StartDate) + .AsNoTracking() + .ToArrayAsync(token) + .ConfigureAwait(false); - var dtos = entities.Select(Convert).ToList(); + var factOperationsForDtos = await GetFactOperationsForDailyReportAsync(idWell, token); - var factOperationsForDtos = await getFactOperationsForDailyReportAsync(idWell, token); - - foreach (var dto in dtos) + var dtos = new List(entities.Length); + foreach (var entity in entities) { - dto.TimeBalance.OperationsStat = (factOperationsForDtos - .Where(o => DateOnly.FromDateTime(o.DateStart) == dto.StartDate) - .GroupBy(o => o.IdCategory) - .Select(g => new OperationStatDto() { Depth = g.Sum(o => o.DepthEnd - o.DepthStart) })); - - await SetUserNamesToDailyReportDtoAsync(dto, token); - } - - + var dto = await Convert(entity, factOperationsForDtos, token); + dtos.Add(dto); + } return dtos; } /// - /// получение фактических операций для суточного рапорта + /// Получение фактических операций для суточного рапорта /// /// /// /// - private async Task> getFactOperationsForDailyReportAsync(int idWell, CancellationToken token) + private async Task> GetFactOperationsForDailyReportAsync(int idWell, CancellationToken token) { var request = new WellOperationRequest() { @@ -126,9 +115,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport if (block.IdUser is not null) { var user = await userRepository.GetOrDefaultAsync(block.IdUser.Value, token); - block.UserName = user is not null - ? string.Format("{0} {1} {2}", user.Surname, user.Name, user.Patronymic) - : String.Empty; + block.UserName = user is not null ? user.MakeDisplayName() : $"userId:{block.IdUser.Value}"; } } @@ -138,35 +125,23 @@ namespace AsbCloudInfrastructure.Services.DailyReport public async Task AddAsync(int idWell, DateTime startDate, int idUser, CancellationToken token = default) { var well = wellService.GetOrDefault(idWell); - if (well is null || well.Timezone is null) + if (well is null) throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); - var startDateOnly = DateOnly.FromDateTime(startDate); + var startDateOnly = ExtractDate(startDate, well); - var entity = await db.DailyReports - .FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDateOnly, token); - if (entity is not null) - throw new Exception($"daily report on {startDateOnly} already exists"); + var hasEntity = await db.DailyReports + .AnyAsync(r => r.IdWell == idWell && r.StartDate == startDateOnly, token); + if (hasEntity) + throw new ArgumentInvalidException($"daily report on {startDateOnly} already exists", nameof(startDateOnly)); - var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1); - var contractor = well.Companies.FirstOrDefault(company => company.IdCompanyType == 2); - - entity = new AsbCloudDb.Model.DailyReport.DailyReport + var entity = new AsbCloudDb.Model.DailyReport.DailyReport { IdWell = idWell, StartDate = startDateOnly, Info = new DailyReportInfo() { - Head = new Head() - { - ReportDate = startDate.Date, - WellName = well.Caption, - ClusterName = well?.Cluster ?? String.Empty, - Customer = customer?.Caption ?? String.Empty, - Contractor = contractor?.Caption ?? String.Empty, - IdUser = idUser, - LastUpdateDate = DateTimeOffset.Now, - } + Head = CreateHeadDailyReportBlock(well, startDate, idUser) } }; db.DailyReports.Add(entity); @@ -174,31 +149,17 @@ namespace AsbCloudInfrastructure.Services.DailyReport return result; } - public async Task UpdateAsync(int idWell, DateTime date, DailyReportDto dto, CancellationToken token) - { - var dateOffset = date.Date; - var entity = await db.DailyReports - .FirstOrDefaultAsync(r => r.IdWell == idWell && - r.StartDate.Year == dateOffset.Year && - r.StartDate.DayOfYear == dateOffset.DayOfYear - , token); - - if (entity is null) - return 0; - - entity.Info = Convert(dto); - db.DailyReports.Update(entity); - var result = await db.SaveChangesAsync(token); - return result; - } - public async Task UpdateBlockAsync(int idWell, DateTime startDate, ItemInfoDto dto, CancellationToken token) { + var well = wellService.GetOrDefault(idWell); + if (well is null) + throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); + var startDateOnly = DateOnly.FromDateTime(startDate); var entity = await db.DailyReports.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDateOnly, token); if (entity is null) - return 0; + throw new ArgumentInvalidException("Daily report doesn`t exist", nameof(startDate)); dto.LastUpdateDate = DateTimeOffset.Now; if (dto is HeadDto headDto) @@ -207,8 +168,6 @@ namespace AsbCloudInfrastructure.Services.DailyReport entity.Info.Bha = bhaDto.Adapt(); if (dto is NoDrillingDto noDrillingDto) entity.Info.NoDrilling = noDrillingDto.Adapt(); - if (dto is TimeBalanceDto timeBalanceDto) - entity.Info.TimeBalance = timeBalanceDto.Adapt(); if (dto is SaubDto saubDto) entity.Info.Saub = saubDto.Adapt(); if (dto is SignDto signDto) @@ -239,23 +198,73 @@ namespace AsbCloudInfrastructure.Services.DailyReport , token); if (entity is null) - return null; - var dto = Convert(entity); + throw new ArgumentInvalidException("Daily report doesn`t exist", nameof(date)); + + var factOperationsForDtos = await GetFactOperationsForDailyReportAsync(idWell, token); + var dto = await Convert(entity, factOperationsForDtos, token); return dto; } - private static DailyReportDto Convert(AsbCloudDb.Model.DailyReport.DailyReport entity) + /// + /// конвертация данных из модели базы данных в dto + /// + /// модель базы данных + /// список фактичских операций для формирования суточного рапорта + /// + /// + private async Task Convert( + AsbCloudDb.Model.DailyReport.DailyReport entity, + IEnumerable factOperationsForDtos, + CancellationToken token) { var dto = entity.Info.Adapt(); dto.StartDate = entity.StartDate; + + dto.TimeBalance.OperationsStat = (factOperationsForDtos + .Where(o => DateOnly.FromDateTime(o.DateStart) == dto.StartDate) + .GroupBy(o => o.IdCategory) + .Select(g => new OperationStatDto() { Depth = g.Sum(o => o.DepthEnd - o.DepthStart) })); + + await SetUserNamesToDailyReportDtoAsync(dto, token); + return dto; } - private static DailyReportInfo Convert(DailyReportDto dto) + /// + /// Приведение данных к формату DateOnly с учетом часового пояса скважины + /// + /// + /// + /// + private DateOnly ExtractDate(DateTime dateTime, WellDto well) { - var entity = dto.Adapt(); - entity.Head.ReportDate = dto.Head.ReportDate.Date.Date; - return entity; + var dateTimeOffset = dateTime.ToUtcDateTimeOffset(well!.Timezone.Hours); + var date = new DateOnly(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day); + return date; + } + + /// + /// Создание блока "Заголовок" по умолчанию + /// + /// + /// + /// + /// + private Head CreateHeadDailyReportBlock(WellDto well, DateTime startDate, int idUser) + { + var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1); + var contractor = well.Companies.FirstOrDefault(company => company.IdCompanyType == 2); + + return new Head() + { + ReportDate = startDate.Date, + WellName = well.Caption, + ClusterName = well?.Cluster ?? string.Empty, + Customer = customer?.Caption ?? string.Empty, + Contractor = contractor?.Caption ?? string.Empty, + IdUser = idUser, + LastUpdateDate = DateTimeOffset.Now, + }; } } #nullable disable diff --git a/AsbCloudWebApi/Controllers/DailyReportController.cs b/AsbCloudWebApi/Controllers/DailyReportController.cs index bc44a4e1..0c5cfc38 100644 --- a/AsbCloudWebApi/Controllers/DailyReportController.cs +++ b/AsbCloudWebApi/Controllers/DailyReportController.cs @@ -1,4 +1,5 @@ using AsbCloudApp.Data.DailyReport; +using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; @@ -71,19 +72,17 @@ namespace AsbCloudWebApi.Controllers var result = await dailyReportService.AddAsync(idWell, startDate, (int)idUser, token); return Ok(result); } - catch (Exception ex) + catch (ArgumentInvalidException ex) { return BadRequest(ex.Message); } } - - /// /// Сохранение изменений набора данных для формирования рапорта (заголовок) /// /// - /// + /// Дата без учета времени /// /// /// @@ -91,18 +90,14 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateHeadAsync(int idWell, [Required] DateTime date, [Required] HeadDto dto, CancellationToken token = default) { - if (!setEditorIdToDailyReportBlock(dto)) - return Forbid(); - - var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token); - return Ok(result); + return await UpdateReportBlockAsync(idWell, date, dto, token); } /// /// Сохранение изменений набора данных для формирования рапорта (блок КНБК) /// /// - /// + /// Дата без учета времени /// /// /// @@ -110,18 +105,14 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateBhaAsync(int idWell, [Required] DateTime date, [Required] BhaDto dto, CancellationToken token = default) { - if (!setEditorIdToDailyReportBlock(dto)) - return Forbid(); - - var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token); - return Ok(result); + return await UpdateReportBlockAsync(idWell, date, dto, token); } /// /// Сохранение изменений набора данных для формирования рапорта (безметражные работы) /// /// - /// + /// Дата без учета времени /// /// /// @@ -129,18 +120,14 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateNoDrillingAsync(int idWell, [Required] DateTime date, [Required] NoDrillingDto dto, CancellationToken token = default) { - if (!setEditorIdToDailyReportBlock(dto)) - return Forbid(); - - var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token); - return Ok(result); + return await UpdateReportBlockAsync(idWell, date, dto, token); } /// /// Сохранение изменений набора данных для формирования рапорта (САУБ) /// /// - /// + /// Дата без учета времени /// /// /// @@ -148,18 +135,14 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateSaubAsync(int idWell, [Required] DateTime date, [Required] SaubDto dto, CancellationToken token = default) { - if (!setEditorIdToDailyReportBlock(dto)) - return Forbid(); - - var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token); - return Ok(result); + return await UpdateReportBlockAsync(idWell, date, dto, token); } /// /// Сохранение изменений набора данных для формирования рапорта (подпись) /// /// - /// + /// Дата без учета времени /// /// /// @@ -167,7 +150,20 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateSignAsync(int idWell, [Required] DateTime date, [Required] SignDto dto, CancellationToken token = default) { - if (!setEditorIdToDailyReportBlock(dto)) + return await UpdateReportBlockAsync(idWell, date, dto, token); + } + + /// + /// Обновление блока суточного рапорта + /// + /// ключ скважины + /// дата суточного рапорта + /// + /// + /// + private async Task UpdateReportBlockAsync(int idWell, DateTime date, ItemInfoDto dto, CancellationToken token) + { + if (!SetEditorIdToDailyReportBlock(dto)) return Forbid(); var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token); @@ -175,11 +171,11 @@ namespace AsbCloudWebApi.Controllers } /// - /// записать ключ пользователя, вносящего изменения в блок суточного рапорта + /// Записать ключ пользователя, вносящего изменения в блок суточного рапорта /// /// /// - private bool setEditorIdToDailyReportBlock(ItemInfoDto dto) + private bool SetEditorIdToDailyReportBlock(ItemInfoDto dto) { var idUser = User.GetUserId(); if (idUser is null)