Правки по ревью

This commit is contained in:
Olga Nemt 2023-03-24 19:27:30 +14:00
parent 7997639e6c
commit 510595239c
8 changed files with 117 additions and 217 deletions

View File

@ -4,6 +4,7 @@ namespace AsbCloudApp.Data.DailyReport
{
/// <summary>
/// хранение дополнительной информации о записи
/// автоматическое формирование данных на серверной стороне
/// </summary>
public class ItemInfoDto
{

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudApp.Data.DailyReport
{
@ -11,7 +12,7 @@ namespace AsbCloudApp.Data.DailyReport
/// <summary>
/// Статистика по операциям
/// </summary>
public IEnumerable<OperationStatDto>? OperationsStat { get; set; }
public IEnumerable<OperationStatDto> OperationsStat { get; set; } = Enumerable.Empty<OperationStatDto>();
}
}

View File

@ -32,16 +32,6 @@ namespace AsbCloudApp.Services
/// <returns></returns>
Task<int> AddAsync(int idWell, DateTime startDate, int idUser, CancellationToken token = default);
/// <summary>
/// изменить данные для суточного рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> UpdateAsync(int idWell, DateTime date, DailyReportDto dto, CancellationToken token = default);
/// <summary>
/// Сформировать файл рапорта
/// </summary>

View File

@ -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();
}

View File

@ -12,6 +12,6 @@ namespace AsbCloudDb.Model
/// <summary>
/// дата последнего обновления блока
/// </summary>
public DateTimeOffset? LastUpdateDate { get; set; }
public DateTimeOffset LastUpdateDate { get; set; } = DateTimeOffset.Now;
}
}

View File

@ -1,96 +0,0 @@
namespace AsbCloudDb.Model.DailyReport
{
public class TimeBalance : ItemInfo
{
/// <summary>
/// Бурение
/// </summary>
public string Drilling { get; set; } = string.Empty;
/// <summary>
/// Промывка
/// </summary>
public string Flushing { get; set; } = string.Empty;
/// <summary>
/// Наращивание
/// </summary>
public string Building { get; set; } = string.Empty;
/// <summary>
/// Проработка
/// </summary>
public string Elaboration { get; set; } = string.Empty;
/// <summary>
/// Расширка
/// </summary>
public string Extension { get; set; } = string.Empty;
/// <summary>
/// Ремонт
/// </summary>
public string Repair { get; set; } = string.Empty;
/// <summary>
/// КНБК
/// </summary>
public string Knbk { get; set; } = string.Empty;
/// <summary>
/// СПО
/// </summary>
public string Spo { get; set; } = string.Empty;
/// <summary>
/// ПЗР
/// </summary>
public string Pzr { get; set; } = string.Empty;
/// <summary>
/// ПВО
/// </summary>
public string Pvo { get; set; } = string.Empty;
/// <summary>
/// ПГР
/// </summary>
public string Pgr { get; set; } = string.Empty;
/// <summary>
/// ГИС
/// </summary>
public string Gis { get; set; } = string.Empty;
/// <summary>
/// ОЗЦ
/// </summary>
public string Ozc { get; set; } = string.Empty;
/// <summary>
/// Тех. работы
/// </summary>
public string EngineeringWorks { get; set; } = string.Empty;
/// <summary>
/// Снятие замера
/// </summary>
public string TakingMeasure { get; set; } = string.Empty;
/// <summary>
/// Цементирование
/// </summary>
public string Cementing { get; set; } = string.Empty;
/// <summary>
/// Простой
/// </summary>
public string Simple { get; set; } = string.Empty;
/// <summary>
/// НПВ
/// </summary>
public string Npv { get; set; } = string.Empty;
}
}

View File

@ -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<DailyReportDto>(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;
}
/// <summary>
/// получение фактических операций для суточного рапорта
/// Получение фактических операций для суточного рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
private async Task<IEnumerable<WellOperationDto>> getFactOperationsForDailyReportAsync(int idWell, CancellationToken token)
private async Task<IEnumerable<WellOperationDto>> 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<int> 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<int> 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<int> 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<Bha>();
if (dto is NoDrillingDto noDrillingDto)
entity.Info.NoDrilling = noDrillingDto.Adapt<NoDrilling>();
if (dto is TimeBalanceDto timeBalanceDto)
entity.Info.TimeBalance = timeBalanceDto.Adapt<TimeBalance>();
if (dto is SaubDto saubDto)
entity.Info.Saub = saubDto.Adapt<Saub>();
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)
/// <summary>
/// конвертация данных из модели базы данных в dto
/// </summary>
/// <param name="entity">модель базы данных</param>
/// <param name="factOperationsForDtos">список фактичских операций для формирования суточного рапорта</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task<DailyReportDto> Convert(
AsbCloudDb.Model.DailyReport.DailyReport entity,
IEnumerable<WellOperationDto> factOperationsForDtos,
CancellationToken token)
{
var dto = entity.Info.Adapt<DailyReportDto>();
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)
/// <summary>
/// Приведение данных к формату DateOnly с учетом часового пояса скважины
/// </summary>
/// <param name="dateTime"></param>
/// <param name="well"></param>
/// <returns></returns>
private DateOnly ExtractDate(DateTime dateTime, WellDto well)
{
var entity = dto.Adapt<DailyReportInfo>();
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;
}
/// <summary>
/// Создание блока "Заголовок" по умолчанию
/// </summary>
/// <param name="well"></param>
/// <param name="startDate"></param>
/// <param name="idUser"></param>
/// <returns></returns>
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

View File

@ -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);
}
}
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (заголовок)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
@ -91,18 +90,14 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> 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);
}
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (блок КНБК)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
@ -110,18 +105,14 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> 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);
}
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (безметражные работы)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
@ -129,18 +120,14 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> 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);
}
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (САУБ)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
@ -148,18 +135,14 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> 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);
}
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (подпись)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
@ -167,7 +150,20 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> UpdateSignAsync(int idWell, [Required] DateTime date, [Required] SignDto dto, CancellationToken token = default)
{
if (!setEditorIdToDailyReportBlock(dto))
return await UpdateReportBlockAsync(idWell, date, dto, token);
}
/// <summary>
/// Обновление блока суточного рапорта
/// </summary>
/// <param name="idWell">ключ скважины</param>
/// <param name="date">дата суточного рапорта</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
private async Task<IActionResult> 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
}
/// <summary>
/// записать ключ пользователя, вносящего изменения в блок суточного рапорта
/// Записать ключ пользователя, вносящего изменения в блок суточного рапорта
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
private bool setEditorIdToDailyReportBlock(ItemInfoDto dto)
private bool SetEditorIdToDailyReportBlock(ItemInfoDto dto)
{
var idUser = User.GetUserId();
if (idUser is null)