From ea8352f4de946e496b6441844b0574f47443de6c Mon Sep 17 00:00:00 2001 From: "Egor A. Tiunov" Date: Tue, 20 Feb 2024 16:58:40 +0500 Subject: [PATCH 01/14] =?UTF-8?q?#28835068=20=D0=A1=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B0?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=BD=D0=B0=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B5=20=D0=BF=D0=BE=20-=D0=B1=D1=83=D1=80=D0=B8=D0=BB?= =?UTF-8?q?=D1=8C=D1=89=D0=B8=D0=BA=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudApp/Data/CompanyDto.cs | 5 +- .../Data/DrillerDetectedOperationStatDto.cs | 12 + AsbCloudApp/Requests/GetStatRequest.cs | 9 + AsbCloudApp/Services/IScheduleService.cs | 9 + AsbCloudApp/Services/ISubsystemService.cs | 6 +- .../Repository/ScheduleRepository.cs | 16 + .../Services/Subsystems/SubsystemService.cs | 440 ++++++++++-------- .../Subsystems/SubsystemController.cs | 18 +- 8 files changed, 320 insertions(+), 195 deletions(-) create mode 100644 AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs create mode 100644 AsbCloudApp/Requests/GetStatRequest.cs diff --git a/AsbCloudApp/Data/CompanyDto.cs b/AsbCloudApp/Data/CompanyDto.cs index 3c670412..f394e40e 100644 --- a/AsbCloudApp/Data/CompanyDto.cs +++ b/AsbCloudApp/Data/CompanyDto.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using AsbCloudApp.Data.User; +using System.ComponentModel.DataAnnotations; namespace AsbCloudApp.Data { diff --git a/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs b/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs new file mode 100644 index 00000000..d350c838 --- /dev/null +++ b/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using AsbCloudApp.Data.Subsystems; + +namespace AsbCloudApp.Data; + +public record DrillerDetectedOperationStatDto +{ + public DrillerDto driller; + public IEnumerable statistic; + public ScheduleDto schedule; + public IEnumerable well; +} \ No newline at end of file diff --git a/AsbCloudApp/Requests/GetStatRequest.cs b/AsbCloudApp/Requests/GetStatRequest.cs new file mode 100644 index 00000000..607c0fc6 --- /dev/null +++ b/AsbCloudApp/Requests/GetStatRequest.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace AsbCloudApp.Requests; + +public class GetStatRequest: RequestBase +{ + public IEnumerable idWell; + public int? idDriller; +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IScheduleService.cs b/AsbCloudApp/Services/IScheduleService.cs index c4c0c1f5..5a28b4c2 100644 --- a/AsbCloudApp/Services/IScheduleService.cs +++ b/AsbCloudApp/Services/IScheduleService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Requests; namespace AsbCloudApp.Services { @@ -28,5 +29,13 @@ namespace AsbCloudApp.Services /// /// Task GetOrDefaultDrillerAsync(int idWell, DateTime workTime, CancellationToken token); + + /// + /// Получить расписание смен + /// + /// + /// + /// + Task> GetPageAsync(GetStatRequest request, CancellationToken token); } } diff --git a/AsbCloudApp/Services/ISubsystemService.cs b/AsbCloudApp/Services/ISubsystemService.cs index 737cca4f..7ccc0aa1 100644 --- a/AsbCloudApp/Services/ISubsystemService.cs +++ b/AsbCloudApp/Services/ISubsystemService.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data; namespace AsbCloudApp.Services; @@ -26,5 +27,8 @@ public interface ISubsystemService /// /// /// - Task> GetStatByActiveWells(IEnumerable wellIds, CancellationToken token); + Task> GetStatByActiveWells(IEnumerable wellIds, CancellationToken token); + + Task> GetByWellsAsync(GetStatRequest request, + CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs index 92676cd4..971cd735 100644 --- a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs +++ b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Requests; using Mapster; namespace AsbCloudInfrastructure.Repository @@ -53,6 +54,21 @@ namespace AsbCloudInfrastructure.Repository return entity?.Driller.Adapt(); } + public async Task> GetPageAsync(GetStatRequest request, CancellationToken token) + { + var idWell = request.idWell; + var idDriller = request.idDriller; + var query = GetQuery().Where(s => request.idWell.Contains(s.IdWell)); + if (idDriller is not null) + { + query.Where(s => s.IdDriller == idDriller); + } + + var result = await query.ToArrayAsync(token); + return result.Select(Convert); + + } + private IQueryable BuildQuery(int idWell, DateTime workTime) { var hoursOffset = wellService.GetTimezone(idWell).Hours; diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs index 93c5ab2f..36f373b0 100644 --- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs +++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs @@ -1,245 +1,309 @@ -using AsbCloudApp.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; using AsbCloudApp.Data.DetectedOperation; using AsbCloudApp.Data.Subsystems; using AsbCloudApp.Exceptions; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using AsbCloudInfrastructure.Services.DetectOperations; namespace AsbCloudInfrastructure.Services.Subsystems; internal class SubsystemService : ISubsystemService { - private const int IdSubsystemAPD = 1; - private const int IdSubsystemAPDRotor = 11; - private const int IdSubsystemAPDSlide = 12; - private const int IdSubsystemOscillation = 65536; + private const int IdSubsystemAPD = 1; + private const int IdSubsystemAPDRotor = 11; + private const int IdSubsystemAPDSlide = 12; + private const int IdSubsystemOscillation = 65536; - private readonly ICrudRepository subsystemRepository; + private readonly ICrudRepository subsystemRepository; - private readonly IWellService wellService; - private readonly IDetectedOperationService detectedOperationService; + private readonly IWellService wellService; + private readonly IDetectedOperationService detectedOperationService; + private readonly IScheduleRepository scheduleRepository; - private IDictionary subsystems = new Dictionary(); + private IDictionary subsystems = new Dictionary(); - public SubsystemService(ICrudRepository subsystemRepository, - IWellService wellService, - IDetectedOperationService detectedOperationService) - { - this.wellService = wellService; - this.subsystemRepository = subsystemRepository; - this.detectedOperationService = detectedOperationService; - } + public SubsystemService(ICrudRepository subsystemRepository, + IWellService wellService, + IDetectedOperationService detectedOperationService, + IScheduleRepository scheduleRepository) + { + this.wellService = wellService; + this.subsystemRepository = subsystemRepository; + this.detectedOperationService = detectedOperationService; + this.scheduleRepository = scheduleRepository; + } - public async Task> GetStatAsync(SubsystemRequest request, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(request.IdWell, token) - ?? throw new ArgumentInvalidException(nameof(request.IdWell), $"Well Id: {request.IdWell} does not exist"); - - if(!well.IdTelemetry.HasValue) - return Enumerable.Empty(); - - var detectedOperationSummaryRequest = new DetectedOperationByWellRequest + // получить расписания бурильщиков по скважинам // ScheduleRepository добавить новый метод + // [ + // get telemetryId by idWell // IWellService.GetOrDefaultStatAsync + // получить detectedOperation by telemetry //detectedOperationService.GetOperationsAsync + // сгруппировать по бурильщикам + // [ + // рассчитать статистику // CalcStatAsync + // join driller from group + // ] + // join well (cluster, deposit) + // ] + public async Task> GetByWellsAsync(GetStatRequest request, + CancellationToken token) + { + var result = new List(); + var schedulePage = await scheduleRepository.GetPageAsync(request, token); + var wellTree = await wellService.GetAsync(new WellRequest { Ids = request.idWell }, token); + var wellGroup = wellTree.GroupBy(w => w.Id); + + foreach (var schedule in schedulePage) { - IdWell = request.IdWell, - IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, + var idWell = schedule.IdWell; + var well = wellGroup?.FirstOrDefault(w=> w.Key == idWell); - GeDateStart = request.GeDate, - LeDateEnd = request.LeDate, + var byWellRequest = new DetectedOperationByWellRequest(idWell, new DetectedOperationRequest()); - GeDepthStart = request.GeDepth, - LeDepthEnd = request.LeDepth, - }; + var detectedOperations = await detectedOperationService + .GetOperationsAsync(byWellRequest, token); - var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest, - token); + var groupByDriller = detectedOperations + .Where(operation => operation.Driller is not null) + .GroupBy(operation => operation.Driller); - if (request.IdDriller.HasValue) - operations = operations.Where(o => o.Driller is not null && o.Driller.Id == request.IdDriller.Value); + foreach (var entry in groupByDriller) + { + var drillerOperationsStat = await CalcStatAsync(entry, token); + var dto = new DrillerDetectedOperationStatDto + { + driller = entry.Key!, + statistic = drillerOperationsStat, + schedule = schedule, + well = well! + }; + result.Add(dto); + } + } - if (!operations.Any()) - return Enumerable.Empty(); + return await Task.FromResult(result); + } - var stat = await CalcStatAsync(operations, token); - return stat; - } + public async Task> GetStatAsync(SubsystemRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(request.IdWell, token) + ?? throw new ArgumentInvalidException(nameof(request.IdWell), + $"Well Id: {request.IdWell} does not exist"); - public async Task> GetStatByActiveWells(IEnumerable wellIds, CancellationToken token) - { - var activeWells = await wellService.GetAsync(new() { Ids = wellIds, IdState = 1 }, token); - var result = await GetStatAsync(activeWells, null, null, token); - return result; - } - - private async Task> CalcStatAsync(IEnumerable operations, CancellationToken token) - { - if (!subsystems.Any()) - subsystems = (await subsystemRepository.GetAllAsync(token)).ToDictionary(s => s.Id, s => s); + if (!well.IdTelemetry.HasValue) + return Enumerable.Empty(); - var oscillationStat = CalcOscillationStat(operations); - var apdStat = CalcApdStat(operations); + var detectedOperationSummaryRequest = new DetectedOperationByWellRequest + { + IdWell = request.IdWell, + IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, - var stat = new List { oscillationStat }; - stat.AddRange(apdStat); + GeDateStart = request.GeDate, + LeDateEnd = request.LeDate, - return stat; - } + GeDepthStart = request.GeDepth, + LeDepthEnd = request.LeDepth, + }; - private SubsystemStatDto CalcOscillationStat(IEnumerable operations) - { - operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); + var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest, + token); - var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(IdSubsystemOscillation, operations); + if (request.IdDriller.HasValue) + operations = operations.Where(o => o.Driller is not null && o.Driller.Id == request.IdDriller.Value); - var oscillationStat = new SubsystemStatDto - { - IdSubsystem = IdSubsystemOscillation, - SubsystemName = subsystems.TryGetValue(IdSubsystemOscillation, out var subsystemDto) ? subsystemDto.Name : "unknown", - UsedTimeHours = usedTimeHours, - SumOperationDepthInterval = operations.Sum(o => o.DepthEnd - o.DepthStart), - SumOperationDurationHours = operations.Sum(o => o.DurationMinutes / 60), - SumDepthInterval = sumDepthInterval, - OperationCount = operationCount, - }; - - oscillationStat.KUsage = oscillationStat.SumDepthInterval / oscillationStat.SumOperationDepthInterval; - - return oscillationStat; - } + if (!operations.Any()) + return Enumerable.Empty(); - private IEnumerable CalcApdStat(IEnumerable operations) - { - var apdRotorAndSlide = operations - .Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory)) - .GroupBy(o => o.IdCategory) - .Select(group => - { - var idSubsystem = group.Key switch - { - WellOperationCategory.IdRotor => IdSubsystemAPDRotor, - WellOperationCategory.IdSlide => IdSubsystemAPDSlide, - _ => throw new ArgumentException($"IdCategory: {group.Key} does not supported in this method", nameof(group.Key)) - }; + var stat = await CalcStatAsync(operations, token); + return stat; + } - var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(idSubsystem, group); + public async Task> GetStatByActiveWells(IEnumerable wellIds, + CancellationToken token) + { + var activeWells = await wellService.GetAsync(new() { Ids = wellIds, IdState = 1 }, token); + var result = await GetStatAsync(activeWells, null, null, token); + return result; + } - var subsystemStat = new SubsystemStatDto - { - IdSubsystem = idSubsystem, - SubsystemName = subsystems.TryGetValue(idSubsystem, out var subsystemDto) ? subsystemDto.Name : "unknown", - UsedTimeHours = usedTimeHours, - SumOperationDepthInterval = group.Sum(o => o.DepthEnd - o.DepthStart), - SumOperationDurationHours = group.Sum(o => o.DurationMinutes / 60), - SumDepthInterval = sumDepthInterval, - OperationCount = operationCount, - }; + private async Task> CalcStatAsync( + IEnumerable operations, CancellationToken token) + { + if (!subsystems.Any()) + subsystems = (await subsystemRepository.GetAllAsync(token)).ToDictionary(s => s.Id, s => s); - subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval; + var oscillationStat = CalcOscillationStat(operations); + var apdStat = CalcApdStat(operations); - return subsystemStat; - }); - - if (!apdRotorAndSlide.Any()) - return Enumerable.Empty(); - - var apdSum = new SubsystemStatDto - { - IdSubsystem = IdSubsystemAPD, - SubsystemName = subsystems.TryGetValue(IdSubsystemAPD, out var subsystemDto) ? subsystemDto.Name : "unknown", - UsedTimeHours = apdRotorAndSlide.Sum(part => part.UsedTimeHours), - SumOperationDepthInterval = apdRotorAndSlide.Sum(part => part.SumOperationDepthInterval), - SumOperationDurationHours = apdRotorAndSlide.Sum(part => part.SumOperationDurationHours), - SumDepthInterval = apdRotorAndSlide.Sum(part => part.SumDepthInterval), - OperationCount = apdRotorAndSlide.Sum(part => part.OperationCount), - }; - - apdSum.KUsage = apdSum.SumDepthInterval / apdSum.SumOperationDepthInterval; + var stat = new List { oscillationStat }; + stat.AddRange(apdStat); - var apdStat = new List { apdSum }; - apdStat.AddRange(apdRotorAndSlide); + return stat; + } - return apdStat; - } + private SubsystemStatDto CalcOscillationStat(IEnumerable operations) + { + operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); - private static (double SumDepthInterval, double UsedTimeHours, int Count) AggregateOperations(int idSubsystem, - IEnumerable operations) => - idSubsystem switch - { - IdSubsystemAPDRotor => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoRotor), - IdSubsystemAPDSlide => CalcOperationsByEnableSubsystems(operations, - EnabledSubsystemsFlags.AutoSlide | EnabledSubsystemsFlags.AutoOscillation), - IdSubsystemOscillation => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoOscillation), - _ => throw new ArgumentException($"IdSubsystem: {idSubsystem} does not supported in this method", nameof(idSubsystem)) - }; + var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(IdSubsystemOscillation, operations); - private static (double SumDepthInterval, double UsedTimeHours, int OperationCount) CalcOperationsByEnableSubsystems( - IEnumerable operations, - EnabledSubsystemsFlags enabledSubsystems) - { - var filtered = operations.Where(o => enabledSubsystems.HasEnabledSubsystems(o.EnabledSubsystems)); + var oscillationStat = new SubsystemStatDto + { + IdSubsystem = IdSubsystemOscillation, + SubsystemName = subsystems.TryGetValue(IdSubsystemOscillation, out var subsystemDto) + ? subsystemDto.Name + : "unknown", + UsedTimeHours = usedTimeHours, + SumOperationDepthInterval = operations.Sum(o => o.DepthEnd - o.DepthStart), + SumOperationDurationHours = operations.Sum(o => o.DurationMinutes / 60), + SumDepthInterval = sumDepthInterval, + OperationCount = operationCount, + }; - var sumDepthInterval = filtered.Sum(o => o.DepthEnd - o.DepthStart); - var usedTimeHours = filtered.Sum(o => o.DurationMinutes / 60); - var operationCount = filtered.Count(); + oscillationStat.KUsage = oscillationStat.SumDepthInterval / oscillationStat.SumOperationDepthInterval; - return (sumDepthInterval, usedTimeHours, operationCount); - } + return oscillationStat; + } - private async Task> GetStatAsync(IEnumerable wells, - DateTime? geDate, - DateTime? leDate, - CancellationToken token) - { - if (!wells.Any()) - return Enumerable.Empty(); + private IEnumerable CalcApdStat(IEnumerable operations) + { + var apdRotorAndSlide = operations + .Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory)) + .GroupBy(o => o.IdCategory) + .Select(group => + { + var idSubsystem = group.Key switch + { + WellOperationCategory.IdRotor => IdSubsystemAPDRotor, + WellOperationCategory.IdSlide => IdSubsystemAPDSlide, + _ => throw new ArgumentException($"IdCategory: {group.Key} does not supported in this method", + nameof(group.Key)) + }; - var idsTelemetries = wells - .Where(w => w.IdTelemetry is not null) - .Select(w => w.IdTelemetry!.Value) - .Distinct(); + var (sumDepthInterval, usedTimeHours, operationCount) = AggregateOperations(idSubsystem, group); - var wellsStat = new List(); + var subsystemStat = new SubsystemStatDto + { + IdSubsystem = idSubsystem, + SubsystemName = subsystems.TryGetValue(idSubsystem, out var subsystemDto) + ? subsystemDto.Name + : "unknown", + UsedTimeHours = usedTimeHours, + SumOperationDepthInterval = group.Sum(o => o.DepthEnd - o.DepthStart), + SumOperationDurationHours = group.Sum(o => o.DurationMinutes / 60), + SumDepthInterval = sumDepthInterval, + OperationCount = operationCount, + }; - foreach (var well in wells) - { - var hoursOffset = well.Timezone.Hours; + subsystemStat.KUsage = subsystemStat.SumDepthInterval / subsystemStat.SumOperationDepthInterval; - var geDateStartUtc = geDate?.ToUtcDateTimeOffset(hoursOffset); + return subsystemStat; + }); - var leDateUtc = leDate?.ToUtcDateTimeOffset(hoursOffset); + if (!apdRotorAndSlide.Any()) + return Enumerable.Empty(); - var request = new DetectedOperationByWellRequest - { - IdWell = well.Id, - IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, - GeDateStart = geDateStartUtc, - LeDateEnd = leDateUtc, - }; + var apdSum = new SubsystemStatDto + { + IdSubsystem = IdSubsystemAPD, + SubsystemName = + subsystems.TryGetValue(IdSubsystemAPD, out var subsystemDto) ? subsystemDto.Name : "unknown", + UsedTimeHours = apdRotorAndSlide.Sum(part => part.UsedTimeHours), + SumOperationDepthInterval = apdRotorAndSlide.Sum(part => part.SumOperationDepthInterval), + SumOperationDurationHours = apdRotorAndSlide.Sum(part => part.SumOperationDurationHours), + SumDepthInterval = apdRotorAndSlide.Sum(part => part.SumDepthInterval), + OperationCount = apdRotorAndSlide.Sum(part => part.OperationCount), + }; - var telemetryOperations = await detectedOperationService - .GetOperationsAsync(request, token); + apdSum.KUsage = apdSum.SumDepthInterval / apdSum.SumOperationDepthInterval; - var wellStat = new SubsystemActiveWellStatDto { Well = well }; + var apdStat = new List { apdSum }; + apdStat.AddRange(apdRotorAndSlide); - if (!telemetryOperations.Any()) - continue; + return apdStat; + } - var subsystemStat = await CalcStatAsync(telemetryOperations, token); + private static (double SumDepthInterval, double UsedTimeHours, int Count) AggregateOperations(int idSubsystem, + IEnumerable operations) => + idSubsystem switch + { + IdSubsystemAPDRotor => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoRotor), + IdSubsystemAPDSlide => CalcOperationsByEnableSubsystems(operations, + EnabledSubsystemsFlags.AutoSlide | EnabledSubsystemsFlags.AutoOscillation), + IdSubsystemOscillation => CalcOperationsByEnableSubsystems(operations, + EnabledSubsystemsFlags.AutoOscillation), + _ => throw new ArgumentException($"IdSubsystem: {idSubsystem} does not supported in this method", + nameof(idSubsystem)) + }; - if (!subsystemStat.Any()) - continue; + private static (double SumDepthInterval, double UsedTimeHours, int OperationCount) CalcOperationsByEnableSubsystems( + IEnumerable operations, + EnabledSubsystemsFlags enabledSubsystems) + { + var filtered = operations.Where(o => enabledSubsystems.HasEnabledSubsystems(o.EnabledSubsystems)); - wellStat.SubsystemAPD = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAPD); - wellStat.SubsystemOscillation = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemOscillation); - wellsStat.Add(wellStat); - } + var sumDepthInterval = filtered.Sum(o => o.DepthEnd - o.DepthStart); + var usedTimeHours = filtered.Sum(o => o.DurationMinutes / 60); + var operationCount = filtered.Count(); - return wellsStat; - } + return (sumDepthInterval, usedTimeHours, operationCount); + } + + private async Task> GetStatAsync(IEnumerable wells, + DateTime? geDate, + DateTime? leDate, + CancellationToken token) + { + if (!wells.Any()) + return Enumerable.Empty(); + + var idsTelemetries = wells + .Where(w => w.IdTelemetry is not null) + .Select(w => w.IdTelemetry!.Value) + .Distinct(); + + var wellsStat = new List(); + + foreach (var well in wells) + { + var hoursOffset = well.Timezone.Hours; + + var geDateStartUtc = geDate?.ToUtcDateTimeOffset(hoursOffset); + + var leDateUtc = leDate?.ToUtcDateTimeOffset(hoursOffset); + + var request = new DetectedOperationByWellRequest + { + IdWell = well.Id, + IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, + GeDateStart = geDateStartUtc, + LeDateEnd = leDateUtc, + }; + + var telemetryOperations = await detectedOperationService + .GetOperationsAsync(request, token); + + var wellStat = new SubsystemActiveWellStatDto { Well = well }; + + if (!telemetryOperations.Any()) + continue; + + var subsystemStat = await CalcStatAsync(telemetryOperations, token); + + if (!subsystemStat.Any()) + continue; + + wellStat.SubsystemAPD = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemAPD); + wellStat.SubsystemOscillation = subsystemStat.FirstOrDefault(s => s.IdSubsystem == IdSubsystemOscillation); + wellsStat.Add(wellStat); + } + + return wellsStat; + } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs index 183073c7..19c21641 100644 --- a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs +++ b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs @@ -22,7 +22,7 @@ namespace AsbCloudWebApi.Controllers.Subsystems private readonly ISubsystemService subsystemService; private readonly ITelemetryDataSaubService telemetryDataSaubService; private readonly IWellService wellService; - + public SubsystemController( ISubsystemService subsystemService, IWellService wellService, @@ -32,6 +32,7 @@ namespace AsbCloudWebApi.Controllers.Subsystems this.wellService = wellService; this.telemetryDataSaubService = telemetryDataSaubService; } + /// /// получить статистику /// @@ -61,6 +62,19 @@ namespace AsbCloudWebApi.Controllers.Subsystems return Ok(dateRange); } + [HttpGet("operationsReport/{idWell}")] + [ProducesResponseType(typeof(DrillerDetectedOperationStatDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStatDateRangeAsync([FromRoute] int idWell, GetStatRequest request, + CancellationToken token) + { + if (!await UserHasAccessToWellAsync(idWell, token)) + return Forbid(); + + var result = await subsystemService.GetByWellsAsync(request, token); + + return Ok(result); + } + private async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) { var idCompany = User.GetCompanyId(); @@ -71,4 +85,4 @@ namespace AsbCloudWebApi.Controllers.Subsystems return false; } } -} +} \ No newline at end of file From 2c051d22de91c82a8af22b311a18a418cdb9eb72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 21 Feb 2024 11:17:20 +0300 Subject: [PATCH 02/14] =?UTF-8?q?=D0=92=20excel=20=D1=83=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=20=D0=BF=D0=B8=D1=88=D0=B5=D1=82=D1=81=D1=8F=20=D0=B2?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D1=8F=20=D1=81=20=D1=87=D0=B0=D1=81=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=BC=20=D0=BF=D0=BE=D1=8F=D1=81=D0=BE=D0=BC,=20?= =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=8D=D1=82?= =?UTF-8?q?=D0=BE=D1=82=20=D0=BC=D0=BE=D0=BC=D0=B5=D0=BD=D1=82,=20=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=20=D0=BA=D0=B0=D0=BA=20=D0=BD=D0=B0=D0=BC=20=D1=81?= =?UTF-8?q?=D0=B5=D0=B9=D1=87=D0=B0=D1=81=20=D0=BD=D0=B5=20=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D0=B1=D1=83=D0=B5=D1=82=D1=81=D1=8F=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=20=D1=8D=D0=BA=D1=81=D0=BF=D0=BE=D1=80=D1=82=D0=B5=20=D1=83?= =?UTF-8?q?=D0=BA=D0=B0=D0=B7=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D1=87=D0=B0?= =?UTF-8?q?=D1=81=D0=BE=D0=B2=D0=BE=D0=B9=20=D0=BF=D0=BE=D1=8F=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/WellOperationImport/WellOperationExportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs index 89cf1494..5ce7a2e2 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs @@ -96,7 +96,7 @@ public class WellOperationExportService : IWellOperationExportService row.Cell(DefaultTemplateInfo.ColumnCategoryInfo).SetCellValue(operation.CategoryInfo); row.Cell(DefaultTemplateInfo.ColumnDepthStart).SetCellValue(operation.DepthStart); row.Cell(DefaultTemplateInfo.ColumnDepthEnd).SetCellValue(operation.DepthEnd); - row.Cell(DefaultTemplateInfo.ColumnDate).SetCellValue(operation.DateStart); + row.Cell(DefaultTemplateInfo.ColumnDate).SetCellValue(operation.DateStart.DateTime); row.Cell(DefaultTemplateInfo.ColumnDuration).SetCellValue(operation.DurationHours); row.Cell(DefaultTemplateInfo.ColumnComment).SetCellValue(operation.Comment); } From 6b94f79f8d318c18ae85f4f204a9ae615d6a5a57 Mon Sep 17 00:00:00 2001 From: Frolov-Nikita Date: Wed, 21 Feb 2024 18:11:47 +0500 Subject: [PATCH 03/14] =?UTF-8?q?#28835068=20=D0=94=D0=BE=D0=BA=D1=83?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5,=20=D0=BC=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/DrillerDetectedOperationStatDto.cs | 23 +++++++++++++++---- AsbCloudApp/Requests/GetStatRequest.cs | 15 ++++++++++-- AsbCloudApp/Services/ISubsystemService.cs | 6 +++++ .../Repository/ScheduleRepository.cs | 6 ++--- .../Services/Subsystems/SubsystemService.cs | 14 +++++------ .../Subsystems/SubsystemController.cs | 15 ++++++++---- 6 files changed, 56 insertions(+), 23 deletions(-) diff --git a/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs b/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs index d350c838..96a5a232 100644 --- a/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs +++ b/AsbCloudApp/Data/DrillerDetectedOperationStatDto.cs @@ -3,10 +3,23 @@ using AsbCloudApp.Data.Subsystems; namespace AsbCloudApp.Data; -public record DrillerDetectedOperationStatDto +/// +/// +/// +public class DrillerDetectedOperationStatDto { - public DrillerDto driller; - public IEnumerable statistic; - public ScheduleDto schedule; - public IEnumerable well; + /// + /// + /// + public IEnumerable Statistic { get; set; } = null!; + + /// + /// + /// + public ScheduleDto Schedule { get; set; } = null!; + + /// + /// + /// + public WellDto Well { get; set; } = null!; } \ No newline at end of file diff --git a/AsbCloudApp/Requests/GetStatRequest.cs b/AsbCloudApp/Requests/GetStatRequest.cs index 607c0fc6..8794198b 100644 --- a/AsbCloudApp/Requests/GetStatRequest.cs +++ b/AsbCloudApp/Requests/GetStatRequest.cs @@ -1,9 +1,20 @@ using System.Collections.Generic; +using System.Linq; namespace AsbCloudApp.Requests; +/// +/// +/// public class GetStatRequest: RequestBase { - public IEnumerable idWell; - public int? idDriller; + /// + /// id + /// + public IEnumerable IdsWells { get; set; } = Enumerable.Empty(); + + /// + /// id + /// + public int? IdDriller { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Services/ISubsystemService.cs b/AsbCloudApp/Services/ISubsystemService.cs index 7ccc0aa1..b82563f8 100644 --- a/AsbCloudApp/Services/ISubsystemService.cs +++ b/AsbCloudApp/Services/ISubsystemService.cs @@ -29,6 +29,12 @@ public interface ISubsystemService /// Task> GetStatByActiveWells(IEnumerable wellIds, CancellationToken token); + /// + /// Получение статистики по бурильщику + /// + /// + /// + /// Task> GetByWellsAsync(GetStatRequest request, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs index 971cd735..e7c2aa1f 100644 --- a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs +++ b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs @@ -56,9 +56,9 @@ namespace AsbCloudInfrastructure.Repository public async Task> GetPageAsync(GetStatRequest request, CancellationToken token) { - var idWell = request.idWell; - var idDriller = request.idDriller; - var query = GetQuery().Where(s => request.idWell.Contains(s.IdWell)); + var idWell = request.IdsWells; + var idDriller = request.IdDriller; + var query = GetQuery().Where(s => request.IdsWells.Contains(s.IdWell)); if (idDriller is not null) { query.Where(s => s.IdDriller == idDriller); diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs index 36f373b0..ed2571a9 100644 --- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs +++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs @@ -56,13 +56,12 @@ internal class SubsystemService : ISubsystemService { var result = new List(); var schedulePage = await scheduleRepository.GetPageAsync(request, token); - var wellTree = await wellService.GetAsync(new WellRequest { Ids = request.idWell }, token); - var wellGroup = wellTree.GroupBy(w => w.Id); + var wells = await wellService.GetAsync(new WellRequest { Ids = request.IdsWells }, token); foreach (var schedule in schedulePage) { var idWell = schedule.IdWell; - var well = wellGroup?.FirstOrDefault(w=> w.Key == idWell); + var well = wells.FirstOrDefault(w=> w.Id == idWell)!; var byWellRequest = new DetectedOperationByWellRequest(idWell, new DetectedOperationRequest()); @@ -78,16 +77,15 @@ internal class SubsystemService : ISubsystemService var drillerOperationsStat = await CalcStatAsync(entry, token); var dto = new DrillerDetectedOperationStatDto { - driller = entry.Key!, - statistic = drillerOperationsStat, - schedule = schedule, - well = well! + Statistic = drillerOperationsStat, + Schedule = schedule, + Well = well, }; result.Add(dto); } } - return await Task.FromResult(result); + return result; } public async Task> GetStatAsync(SubsystemRequest request, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs index 19c21641..4d16958b 100644 --- a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs +++ b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -62,13 +63,17 @@ namespace AsbCloudWebApi.Controllers.Subsystems return Ok(dateRange); } - [HttpGet("operationsReport/{idWell}")] - [ProducesResponseType(typeof(DrillerDetectedOperationStatDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetStatDateRangeAsync([FromRoute] int idWell, GetStatRequest request, + [HttpGet("drillerDetectedOperationStat")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetByWellsAsync(GetStatRequest request, CancellationToken token) { - if (!await UserHasAccessToWellAsync(idWell, token)) - return Forbid(); + if (!request.IdsWells.Any()) + return NoContent(); + + foreach(var idWell in request.IdsWells) + if (!await UserHasAccessToWellAsync(idWell, token)) + return Forbid(); var result = await subsystemService.GetByWellsAsync(request, token); From 72669b05262f8730c74ba41520aaf74776af5b58 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 22 Feb 2024 10:48:49 +0500 Subject: [PATCH 04/14] fix SubsystemController --- AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs index 4d16958b..f8124d8d 100644 --- a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs +++ b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs @@ -65,7 +65,7 @@ namespace AsbCloudWebApi.Controllers.Subsystems [HttpGet("drillerDetectedOperationStat")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetByWellsAsync(GetStatRequest request, + public async Task GetByWellsAsync([FromQuery] GetStatRequest request, CancellationToken token) { if (!request.IdsWells.Any()) From 2ec609b56f529b75b8012ccdfef2ca6d9878e5c7 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 22 Feb 2024 13:34:05 +0500 Subject: [PATCH 05/14] fix test Check_Exported_WellOperations_With_Operations_In_Db --- .../Repositories/IWellOperationRepository.cs | 9 --- .../Repository/WellOperationRepository.cs | 10 +--- .../WellOperationExportService.cs | 12 ++-- .../WellOperationImportService.cs | 18 ++++-- .../WellOperationExportServiceTest.cs | 58 ++++++++++--------- .../Controllers/WellOperationController.cs | 7 ++- 6 files changed, 56 insertions(+), 58 deletions(-) diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index 2ac586aa..cf277304 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -2,7 +2,6 @@ using AsbCloudApp.Requests; using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; @@ -13,14 +12,6 @@ namespace AsbCloudApp.Repositories /// public interface IWellOperationRepository { - //TODO: replace all references - /// - /// список названий операций - /// - /// - [Obsolete("use IWellOperationCategoryRepository.GetCategories(bool includeParents)")] - IEnumerable GetCategories(bool includeParents); - /// /// Список секций /// diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index c6edb30b..57bf3768 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -23,7 +23,6 @@ namespace AsbCloudInfrastructure.Repository; public class WellOperationRepository : IWellOperationRepository { private const string KeyCacheSections = "OperationsBySectionSummarties"; - private const int Gap = 90; private readonly IAsbCloudDbContext db; private readonly IMemoryCache memoryCache; @@ -38,13 +37,6 @@ public class WellOperationRepository : IWellOperationRepository this.wellOperationCategoryRepository = wellOperationCategoryRepository; } - /// - public IEnumerable GetCategories(bool includeParents) - { - return wellOperationCategoryRepository.Get(includeParents); - } - - /// public IEnumerable GetSectionTypes() => memoryCache .GetOrCreateBasic(db.Set()) @@ -272,7 +264,7 @@ public class WellOperationRepository : IWellOperationRepository DurationDepth = o.DepthEnd - o.DepthStart }) .ToListAsync(token); - var parentRelationDictionary = GetCategories(true) + var parentRelationDictionary = wellOperationCategoryRepository.Get(true) .ToDictionary(c => c.Id, c => new { c.Name, diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs index 5ce7a2e2..142b751f 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs @@ -19,15 +19,19 @@ public class WellOperationExportService : IWellOperationExportService private readonly IWellOperationRepository wellOperationRepository; private readonly IWellService wellService; private readonly IWellOperationImportTemplateService wellOperationImportTemplateService; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - public WellOperationExportService(IWellOperationRepository wellOperationRepository, + public WellOperationExportService( + IWellOperationRepository wellOperationRepository, IWellService wellService, - IWellOperationImportTemplateService wellOperationImportTemplateService) + IWellOperationImportTemplateService wellOperationImportTemplateService, + IWellOperationCategoryRepository wellOperationCategoryRepository) { this.wellOperationRepository = wellOperationRepository; this.wellService = wellService; this.wellOperationImportTemplateService = wellOperationImportTemplateService; - } + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + } public async Task ExportAsync(int idWell, CancellationToken cancellationToken) { @@ -76,7 +80,7 @@ public class WellOperationExportService : IWellOperationExportService var operationsToArray = operations.ToArray(); var sections = wellOperationRepository.GetSectionTypes(); - var categories = wellOperationRepository.GetCategories(false); + var categories = wellOperationCategoryRepository.Get(false); for (int i = 0; i < operationsToArray.Length; i++) { diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs index 800979e5..6ad227a3 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs @@ -14,24 +14,28 @@ public class WellOperationImportService : IWellOperationImportService { private readonly IWellService wellService; private readonly IWellOperationRepository wellOperationRepository; - - private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0); + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0); private static readonly DateTime dateLimitMax = new(2099, 1, 1, 0, 0, 0); private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366); - public WellOperationImportService(IWellService wellService, - IWellOperationRepository wellOperationRepository) + public WellOperationImportService( + IWellService wellService, + IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository + ) { this.wellService = wellService; this.wellOperationRepository = wellOperationRepository; - } + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + } public IEnumerable Import(int idWell, int idUser, int idType, SheetDto sheet) { var validationErrors = new List(); var sections = wellOperationRepository.GetSectionTypes(); - var categories = wellOperationRepository.GetCategories(false); + var categories = wellOperationCategoryRepository.Get(false); var wellOperations = new List(); @@ -83,7 +87,9 @@ public class WellOperationImportService : IWellOperationImportService IdUser = idUser, IdType = idType, IdWellSectionType = section.Id, + WellSectionTypeName = section.Caption, IdCategory = category.Id, + CategoryName = category.Name, CategoryInfo = row.CategoryInfo, DepthStart = row.DepthStart, DepthEnd = row.DepthEnd, diff --git a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs index 3d66aab9..e58adda7 100644 --- a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs @@ -5,6 +5,7 @@ using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.WellOperationImport; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using AsbCloudInfrastructure.Services.WellOperationImport; using AsbCloudInfrastructure.Services.WellOperationImport.FileParser; using NSubstitute; @@ -27,6 +28,7 @@ namespace AsbCloudWebApi.Tests.Services.WellOperationExport private IWellService wellService; private IWellOperationRepository wellOperationRepository; + private IWellOperationCategoryRepository wellOperationCategoryRepository; private IWellOperationImportTemplateService wellOperationImportTemplateService; private WellOperationExportService wellOperationExportService; private WellOperationImportService wellOperationImportService; @@ -114,46 +116,46 @@ namespace AsbCloudWebApi.Tests.Services.WellOperationExport { wellService = Substitute.For(); wellOperationRepository = Substitute.For(); + wellOperationCategoryRepository = Substitute.For(); wellOperationImportTemplateService = new WellOperationImportTemplateService(); - wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellService, wellOperationImportTemplateService); + wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellService, wellOperationImportTemplateService, wellOperationCategoryRepository); - wellOperationImportService = new WellOperationImportService(wellService, wellOperationRepository); + wellOperationImportService = new WellOperationImportService(wellService, wellOperationRepository, wellOperationCategoryRepository); wellOperationDefaultExcelParser = new WellOperationDefaultExcelParser(); this.output = output; } -#warning Test Check_Exported_WellOperations_With_Operations_In_Db Fails and commented for debug deployment task - //[Fact] - //public async Task Check_Exported_WellOperations_With_Operations_In_Db() - //{ - // wellService.GetTimezone(idWell).Returns(new SimpleTimezoneDto() - // { - // Hours = 5 - // }); + [Fact] + public async Task Check_Exported_WellOperations_With_Operations_In_Db() + { + wellService.GetTimezone(idWell).Returns(new SimpleTimezoneDto() + { + Hours = 5 + }); - // var localOperations = operations.ToArray(); - // foreach (var operation in localOperations) - // operation.Id = 0; + var localOperations = operations.ToArray(); + foreach (var operation in localOperations) + operation.Id = 0; - // wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) - // .ReturnsForAnyArgs(localOperations); - // wellOperationRepository.GetSectionTypes().Returns(sectionTypes); - // wellOperationRepository.GetCategories(false).Returns(categories); + wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs(localOperations); + wellOperationRepository.GetSectionTypes().Returns(sectionTypes); + wellOperationCategoryRepository.Get(false).Returns(categories); - // var stream = await wellOperationExportService.ExportAsync(idWell, CancellationToken.None); + var stream = await wellOperationExportService.ExportAsync(idWell, CancellationToken.None); - // var options = new WellOperationImportDefaultOptionsDto - // { - // IdType = WellOperation.IdOperationTypePlan - // }; - // var sheet = wellOperationDefaultExcelParser.Parse(stream, options); - // var result = wellOperationImportService.Import(idWell, 1, options.IdType, sheet); + var options = new WellOperationImportDefaultOptionsDto + { + IdType = WellOperation.IdOperationTypePlan + }; + var sheet = wellOperationDefaultExcelParser.Parse(stream, options); + var result = wellOperationImportService.Import(idWell, 1, options.IdType, sheet); - // var expected = JsonSerializer.Serialize(localOperations); - // var actual = JsonSerializer.Serialize(result); + var expected = JsonSerializer.Serialize(localOperations); + var actual = JsonSerializer.Serialize(result); - // Assert.Equal(expected, actual); - //} + Assert.Equal(expected, actual); + } [Fact] public void TestDataContainsNotDefaultProps() diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index 0d53a4ad..d624e89a 100644 --- a/AsbCloudWebApi/Controllers/WellOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellOperationController.cs @@ -35,6 +35,7 @@ namespace AsbCloudWebApi.Controllers private readonly IWellOperationExportService wellOperationExportService; private readonly IWellOperationImportTemplateService wellOperationImportTemplateService; private readonly IWellOperationImportService wellOperationImportService; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; private readonly IWellOperationExcelParser wellOperationDefaultExcelParser; private readonly IWellOperationExcelParser wellOperationGazpromKhantosExcelParser; private readonly IUserRepository userRepository; @@ -44,6 +45,7 @@ namespace AsbCloudWebApi.Controllers IWellOperationImportTemplateService wellOperationImportTemplateService, IWellOperationExportService wellOperationExportService, IWellOperationImportService wellOperationImportService, + IWellOperationCategoryRepository wellOperationCategoryRepository, IWellOperationExcelParser wellOperationDefaultExcelParser, IWellOperationExcelParser wellOperationGazpromKhantosExcelParser, IUserRepository userRepository) @@ -53,6 +55,7 @@ namespace AsbCloudWebApi.Controllers this.wellOperationImportTemplateService = wellOperationImportTemplateService; this.wellOperationExportService = wellOperationExportService; this.wellOperationImportService = wellOperationImportService; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; this.wellOperationDefaultExcelParser = wellOperationDefaultExcelParser; this.wellOperationGazpromKhantosExcelParser = wellOperationGazpromKhantosExcelParser; this.userRepository = userRepository; @@ -81,7 +84,7 @@ namespace AsbCloudWebApi.Controllers [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public IActionResult GetCategories(bool includeParents = true) { - var result = operationRepository.GetCategories(includeParents); + var result = wellOperationCategoryRepository.Get(includeParents); return Ok(result); } @@ -163,7 +166,7 @@ namespace AsbCloudWebApi.Controllers } /// - /// Статистика операций по скважине, группированая по категориям + /// Статистика операций по скважине, группированная по категориям /// /// id скважины /// From adfd1ad5974a70adfa357e4a2e0ded38eedcec7f Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 22 Feb 2024 13:47:11 +0500 Subject: [PATCH 06/14] GetStatRequest fix init --- AsbCloudApp/Requests/GetStatRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudApp/Requests/GetStatRequest.cs b/AsbCloudApp/Requests/GetStatRequest.cs index 8794198b..5ebb9550 100644 --- a/AsbCloudApp/Requests/GetStatRequest.cs +++ b/AsbCloudApp/Requests/GetStatRequest.cs @@ -11,7 +11,7 @@ public class GetStatRequest: RequestBase /// /// id /// - public IEnumerable IdsWells { get; set; } = Enumerable.Empty(); + public IEnumerable IdsWells { get; set; } = new List(); /// /// id From fd15622ad1a2f2c4df10bab1304ec50dcf2bb797 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 22 Feb 2024 14:00:20 +0500 Subject: [PATCH 07/14] =?UTF-8?q?WellOperationExportService=20=D1=83=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D1=82=D1=8C=20=D0=BD=D0=B5=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=83=D1=8E=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WellOperationImport/WellOperationExportService.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs index 142b751f..96e640b8 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; -using AsbCloudApp.Services; using AsbCloudApp.Services.WellOperationImport; using AsbCloudInfrastructure.Services.WellOperationImport.Constants; using ClosedXML.Excel; @@ -15,20 +14,16 @@ namespace AsbCloudInfrastructure.Services.WellOperationImport; public class WellOperationExportService : IWellOperationExportService { - //TODO: удалить неиспользуемую зависимость private readonly IWellOperationRepository wellOperationRepository; - private readonly IWellService wellService; private readonly IWellOperationImportTemplateService wellOperationImportTemplateService; private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; public WellOperationExportService( IWellOperationRepository wellOperationRepository, - IWellService wellService, IWellOperationImportTemplateService wellOperationImportTemplateService, IWellOperationCategoryRepository wellOperationCategoryRepository) { this.wellOperationRepository = wellOperationRepository; - this.wellService = wellService; this.wellOperationImportTemplateService = wellOperationImportTemplateService; this.wellOperationCategoryRepository = wellOperationCategoryRepository; } From 1de54b43e6b7e54ed41af75bfa74d63ab0208527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Mon, 26 Feb 2024 07:49:15 +0300 Subject: [PATCH 08/14] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=B3=D0=B0=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B1=D1=83=D1=80=D0=B8=D0=BB=D1=8C=D1=89=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B2=20=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudInfrastructure/DependencyInjection.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index ce742684..d61ddc57 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -56,6 +56,10 @@ namespace AsbCloudInfrastructure { public static void MapsterSetup() { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(source => source.Driller); + TypeAdapterConfig.GlobalSettings.Default.Config .ForType() .MapWith((source) => source.DateTime); From c45b58d7379acfca3fc7f381cf9b5350f987eb4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Mon, 26 Feb 2024 11:27:19 +0300 Subject: [PATCH 09/14] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8?= =?UTF-8?q?=20.net=20core=206.0=20->=208.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Обновил все проекты Обновил версии пакетов --- AsbCloudApp/AsbCloudApp.csproj | 12 ++---------- AsbCloudDb/AsbCloudDb.csproj | 6 +++--- AsbCloudInfrastructure/AsbCloudInfrastructure.csproj | 2 +- .../AsbCloudWebApi.IntegrationTests.csproj | 2 +- AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj | 4 +--- AsbCloudWebApi/AsbCloudWebApi.csproj | 2 +- 6 files changed, 9 insertions(+), 19 deletions(-) diff --git a/AsbCloudApp/AsbCloudApp.csproj b/AsbCloudApp/AsbCloudApp.csproj index 79ec9867..cf4f45e5 100644 --- a/AsbCloudApp/AsbCloudApp.csproj +++ b/AsbCloudApp/AsbCloudApp.csproj @@ -1,19 +1,11 @@  - net6.0 + net8.0 true enable - - - - - - - - - + diff --git a/AsbCloudDb/AsbCloudDb.csproj b/AsbCloudDb/AsbCloudDb.csproj index 9d62fdaf..91328b74 100644 --- a/AsbCloudDb/AsbCloudDb.csproj +++ b/AsbCloudDb/AsbCloudDb.csproj @@ -1,16 +1,16 @@ - net6.0 + net8.0 enable - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index 5579d2b2..60b5a3bb 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 enable diff --git a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj index 1c641f69..b97bed80 100644 --- a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj +++ b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable enable af52bb94-3f08-4d6a-8895-8cfb7691c393 diff --git a/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj b/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj index 66a2f309..6305415b 100644 --- a/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj +++ b/AsbCloudWebApi.Tests/AsbCloudWebApi.Tests.csproj @@ -1,10 +1,8 @@  - net6.0 - + net8.0 false - enable diff --git a/AsbCloudWebApi/AsbCloudWebApi.csproj b/AsbCloudWebApi/AsbCloudWebApi.csproj index d0485b9a..0537c3aa 100644 --- a/AsbCloudWebApi/AsbCloudWebApi.csproj +++ b/AsbCloudWebApi/AsbCloudWebApi.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 true true $(NoWarn);1591 From e82720b421e70ae60d04eddbe9dc63fbf72d559e Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 27 Feb 2024 09:32:08 +0500 Subject: [PATCH 10/14] Add abstract class CrudWellRelatedClient --- .../CrudWellRelatedRepositoryBase.cs | 1 - .../Clients/ICrudWellRelatedClient.cs | 29 ++++ .../Controllers/AdminDepositControllerTest.cs | 2 +- .../ProcessMapPlanDrillingControllerTest.cs | 2 +- .../Controllers/ScheduleControllerTest.cs | 159 ++++++++++++++++++ .../Controllers/SlipsStatControllerTest.cs | 2 +- .../WellOperationControllerTest.cs | 2 +- .../WebAppFactoryFixture.cs | 6 +- 8 files changed, 196 insertions(+), 7 deletions(-) create mode 100644 AsbCloudWebApi.IntegrationTests/Clients/ICrudWellRelatedClient.cs create mode 100644 AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs diff --git a/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs b/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs index d788f3d6..d6b267a8 100644 --- a/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs +++ b/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs @@ -43,5 +43,4 @@ namespace AsbCloudInfrastructure.Repository return dtos; } } - } diff --git a/AsbCloudWebApi.IntegrationTests/Clients/ICrudWellRelatedClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/ICrudWellRelatedClient.cs new file mode 100644 index 00000000..7f99ba5f --- /dev/null +++ b/AsbCloudWebApi.IntegrationTests/Clients/ICrudWellRelatedClient.cs @@ -0,0 +1,29 @@ +using AsbCloudApp.Data; +using Refit; + +namespace AsbCloudWebApi.IntegrationTests.Clients; + +public interface ICrudWellRelatedClient + where TDto : IId, IWellRelated +{ + [Post("/")] + Task> InsertAsync([Body] TDto dto); + + [Post("/range")] + Task> InsertRangeAsync([Body] IEnumerable dtos); + + [Get("/")] + Task>> GetAllAsync(); + + [Get("/well/{idWell}")] + Task>> GetByIdWellAsync(int idWell); + + [Get("/{id}")] + Task> GetOrDefaultAsync(int id); + + [Put("/")] + Task> UpdateAsync([Body] TDto dto); + + [Delete("/{id}")] + Task> DeleteAsync(int id); +} diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs index 1d2a2c3c..331c7b7d 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/AdminDepositControllerTest.cs @@ -26,7 +26,7 @@ public class AdminDepositControllerTest : BaseIntegrationTest public AdminDepositControllerTest(WebAppFactoryFixture factory) : base(factory) { - client = factory.GetAuthorizedHttpClient(); + client = factory.GetAuthorizedHttpClient(string.Empty); dbContext.CleanupDbSet(); } diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs index f06e2133..f04ba9ca 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ProcessMapPlan/ProcessMapPlanDrillingControllerTest.cs @@ -82,7 +82,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest public ProcessMapPlanDrillingControllerTest(WebAppFactoryFixture factory) : base(factory) { dbContext.CleanupDbSet(); - client = factory.GetAuthorizedHttpClient(); + client = factory.GetAuthorizedHttpClient(string.Empty); } [Fact] diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs new file mode 100644 index 00000000..ebc52258 --- /dev/null +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs @@ -0,0 +1,159 @@ +using AsbCloudApp.Data; +using AsbCloudDb.Model; +using AsbCloudInfrastructure; +using AsbCloudWebApi.IntegrationTests.Clients; +using Mapster; +using Microsoft.EntityFrameworkCore; +using System.Net; +using Xunit; + +namespace AsbCloudWebApi.IntegrationTests.Controllers +{ + public abstract class CrudWellRelatedClient : BaseIntegrationTest + where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated + where TEntity : class, AsbCloudDb.Model.IId, AsbCloudDb.Model.IWellRelated + { + public abstract IEnumerable ValidDtos { get; } + public abstract IEnumerable InvalidDtos { get; } + protected List ExcludeProps { get; set; } = new() { "Id" }; + + protected ICrudWellRelatedClient client; + + public CrudWellRelatedClient(WebAppFactoryFixture factory, string uriSuffix) + : base(factory) + { + client = factory.GetAuthorizedHttpClient>(uriSuffix); + } + + protected async Task> GetCleanDbSet() + { + var dbset = dbContext.Set(); + dbset.RemoveRange(dbset); + await dbContext.SaveChangesAsync(CancellationToken.None); + return dbset; + } + + [Fact] + public async Task Insert_returns_success() + { + foreach (var validDto in ValidDtos) + await _Insert_returns_success(validDto); + } + + private async Task _Insert_returns_success(TDto validDto) + { + var dbset = await GetCleanDbSet(); + + //act + var response = await client.InsertAsync(validDto); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.True(response.Content > 0); + + var entity = dbset.First(); + var fromDbDto = Convert(entity); + MatchHelper.Match(validDto, fromDbDto, ExcludeProps); + } + + [Fact] + public async Task Insert_fails() + { + foreach (var inValidDto in InvalidDtos) + await _Insert_fails(inValidDto); + } + + private async Task _Insert_fails(TDto invalidDto) + { + var dbset = await GetCleanDbSet(); + //act + var response = await client.InsertAsync(invalidDto); + + //assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + protected virtual TDto Convert(TEntity entity) + { + var dto = entity.Adapt(); + return dto; + } + } + + public class ScheduleControllerTest : CrudWellRelatedClient + { + static DrillerDto driller = new (){ + Id = 2 , + Name = "Name" , + Patronymic = "Patronymic", + Surname = "Surname", + }; + static Well well = Data.Defaults.Wells.First(); + + public override IEnumerable ValidDtos { get; } = new ScheduleDto[] + { + new() { + Id = 1, + IdWell = well.Id, + Driller = driller, + IdDriller = driller.Id, + DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), + DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), + ShiftStart = new TimeDto(8, 0, 0), + ShiftEnd = new TimeDto(20, 0, 0), + }, + new() { + Id = 1, + IdWell = well.Id, + Driller = driller, + IdDriller = driller.Id, + DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), + DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), + ShiftStart = new TimeDto(20, 0, 0), + ShiftEnd = new TimeDto(8, 0, 0), + } + }; + + public override IEnumerable InvalidDtos { get; } = new ScheduleDto[] + { + new() { + Id = 1, + IdWell = well.Id, + Driller = driller, + IdDriller = driller.Id, + DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), + DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), + ShiftStart = new TimeDto(8, 0, 0), + ShiftEnd = new TimeDto(20, 0, 0), + }, + new() { + Id = 1, + IdWell = well.Id, + Driller = driller, + IdDriller = int.MaxValue - 1, + DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), + DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), + ShiftStart = new TimeDto(8, 0, 0), + ShiftEnd = new TimeDto(20, 0, 0), + } + }; + + public ScheduleControllerTest(WebAppFactoryFixture factory) + : base(factory, "api/schedule") + { + var dbDriller = driller.Adapt(); + dbContext.Set().Add(dbDriller); + dbContext.SaveChanges(); + + ExcludeProps.Add(nameof(ScheduleDto.Driller)); + } + + protected override ScheduleDto Convert(Schedule entity) + { + var dto = base.Convert(entity); + dto.DrillStart = entity.DrillStart.ToRemoteDateTime(well.Timezone.Hours); + dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(well.Timezone.Hours); + return dto; + } + } +} diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs index 908d5b95..57eacadf 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/SlipsStatControllerTest.cs @@ -66,7 +66,7 @@ public class SlipsStatControllerTest : BaseIntegrationTest wellOperations.Add(factWellOperation); dbContext.SaveChanges(); - client = factory.GetAuthorizedHttpClient(); + client = factory.GetAuthorizedHttpClient(string.Empty); } [Fact] diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs index a47d5f09..459e6b52 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs @@ -44,7 +44,7 @@ public class WellOperationControllerTest : BaseIntegrationTest public WellOperationControllerTest(WebAppFactoryFixture factory) : base(factory) { - client = factory.GetAuthorizedHttpClient(); + client = factory.GetAuthorizedHttpClient(string.Empty); } /// diff --git a/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs b/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs index aa8bd27e..44bd4b67 100644 --- a/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs +++ b/AsbCloudWebApi.IntegrationTests/WebAppFactoryFixture.cs @@ -83,10 +83,12 @@ public class WebAppFactoryFixture : WebApplicationFactory, return httpClient; } - public T GetAuthorizedHttpClient() + public T GetAuthorizedHttpClient(string uriSuffix) { var httpClient = GetAuthorizedHttpClient(); + if (!string.IsNullOrEmpty(uriSuffix)) + if(httpClient.BaseAddress is not null) + httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); return RestService.For(httpClient, refitSettings); } - } \ No newline at end of file From c0f2bedd61ddbe32861e22d055007c45820b8638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Tue, 27 Feb 2024 09:36:00 +0300 Subject: [PATCH 11/14] fix --- AsbCloudInfrastructure/Services/ReportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 3b7199a9..fd7d86a3 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -204,7 +204,7 @@ public class ReportService : IReportService public async Task DeleteAllOldReportsAsync(TimeSpan lifetime, CancellationToken token) { - var lifeTimeStartDate = DateTime.UtcNow.Date - lifetime; + var lifeTimeStartDate = DateTimeOffset.UtcNow.Date - lifetime; var fileIds = await db.ReportProperties .Where(r => r.File.UploadDate.Date < lifeTimeStartDate) .Select(r => r.IdFile) From a9dc67f83fd123f11f08461641796939719a1688 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 27 Feb 2024 13:44:14 +0500 Subject: [PATCH 12/14] ScheduleDto Add IValidatableObject --- AsbCloudApp/Data/ScheduleDto.cs | 10 +- .../Controllers/ScheduleControllerTest.cs | 117 ++++++++++++++---- .../Data/Defaults.cs | 12 +- 3 files changed, 112 insertions(+), 27 deletions(-) diff --git a/AsbCloudApp/Data/ScheduleDto.cs b/AsbCloudApp/Data/ScheduleDto.cs index ea6d54b0..84cbe515 100644 --- a/AsbCloudApp/Data/ScheduleDto.cs +++ b/AsbCloudApp/Data/ScheduleDto.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace AsbCloudApp.Data @@ -6,7 +7,7 @@ namespace AsbCloudApp.Data /// /// Описание данных графика работ /// - public class ScheduleDto : IId, IWellRelated + public class ScheduleDto : IId, IWellRelated, IValidatableObject { /// [Required] @@ -50,5 +51,12 @@ namespace AsbCloudApp.Data /// Бурильщик /// public DrillerDto? Driller { get; set; } + + /// + public IEnumerable Validate(ValidationContext validationContext) + { + if(DrillStart >= DrillEnd) + yield return new ValidationResult($"DrillStart > DrillEnd"); + } } } diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs index ebc52258..a58e20f1 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/ScheduleControllerTest.cs @@ -4,6 +4,7 @@ using AsbCloudInfrastructure; using AsbCloudWebApi.IntegrationTests.Clients; using Mapster; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; using System.Net; using Xunit; @@ -15,9 +16,10 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers { public abstract IEnumerable ValidDtos { get; } public abstract IEnumerable InvalidDtos { get; } + public abstract IEnumerable ForbiddenDtos { get; } protected List ExcludeProps { get; set; } = new() { "Id" }; - protected ICrudWellRelatedClient client; + protected ICrudWellRelatedClient client; public CrudWellRelatedClient(WebAppFactoryFixture factory, string uriSuffix) : base(factory) @@ -34,13 +36,13 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers } [Fact] - public async Task Insert_returns_success() + public async Task Insert_returns_success_for_validDtos() { foreach (var validDto in ValidDtos) - await _Insert_returns_success(validDto); + await Insert_returns_success(validDto); } - private async Task _Insert_returns_success(TDto validDto) + private async Task Insert_returns_success(TDto validDto) { var dbset = await GetCleanDbSet(); @@ -57,15 +59,16 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers } [Fact] - public async Task Insert_fails() + public async Task Insert_returns_badRequest_for_invalidDtos() { foreach (var inValidDto in InvalidDtos) - await _Insert_fails(inValidDto); + await Insert_returns_badRequest(inValidDto); } - private async Task _Insert_fails(TDto invalidDto) + private async Task Insert_returns_badRequest(TDto invalidDto) { - var dbset = await GetCleanDbSet(); + await GetCleanDbSet(); + //act var response = await client.InsertAsync(invalidDto); @@ -73,21 +76,73 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } + [Fact] + public async Task Insert_returns_forbidden_for_forbiddenDtos() + { + foreach (var forbiddenDto in ForbiddenDtos) + await Insert_returns_forbidden(forbiddenDto); + } + + private async Task Insert_returns_forbidden(TDto forbiddenDto) + { + await GetCleanDbSet(); + + //act + var response = await client.InsertAsync(forbiddenDto); + + //assert + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + } + + [Fact] + public async Task GetAllAsync_returns_data() + { + //arrange + var dbset = await GetCleanDbSet(); + var entries = new List<(EntityEntry, TDto)>(); + + foreach (var dto in ValidDtos) + { + var entity = Convert(dto); + entity.Id = 0; + var entry = dbset.Add(entity); + entries.Add((entry, dto)); + } + dbContext.SaveChanges(); + + //act + var response = await client.GetAllAsync(); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Equal(entries.Count, response.Content.Count()); + + foreach (var item in response.Content) + { + var entry = entries.First(e => e.Item1.Entity.Id == item.Id); + MatchHelper.Match(entry.Item2, item, ExcludeProps); + } + } + protected virtual TDto Convert(TEntity entity) { var dto = entity.Adapt(); return dto; } + + protected virtual TEntity Convert(TDto dto) + { + var entity = dto.Adapt(); + return entity; + } } public class ScheduleControllerTest : CrudWellRelatedClient { - static DrillerDto driller = new (){ - Id = 2 , - Name = "Name" , - Patronymic = "Patronymic", - Surname = "Surname", - }; + static Driller driller = Data.Defaults.Drillers.First(); + static DrillerDto drillerDto = driller.Adapt(); + static Well well = Data.Defaults.Wells.First(); public override IEnumerable ValidDtos { get; } = new ScheduleDto[] @@ -95,7 +150,7 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers new() { Id = 1, IdWell = well.Id, - Driller = driller, + Driller = drillerDto, IdDriller = driller.Id, DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), @@ -105,7 +160,7 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers new() { Id = 1, IdWell = well.Id, - Driller = driller, + Driller = drillerDto, IdDriller = driller.Id, DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), @@ -117,9 +172,8 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers public override IEnumerable InvalidDtos { get; } = new ScheduleDto[] { new() { - Id = 1, IdWell = well.Id, - Driller = driller, + Driller = drillerDto, IdDriller = driller.Id, DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), @@ -127,9 +181,8 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers ShiftEnd = new TimeDto(20, 0, 0), }, new() { - Id = 1, IdWell = well.Id, - Driller = driller, + Driller = drillerDto, IdDriller = int.MaxValue - 1, DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), @@ -138,13 +191,21 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers } }; + public override IEnumerable ForbiddenDtos { get; } = new ScheduleDto[] { + new() { + IdWell = int.MaxValue - 1, + Driller = drillerDto, + IdDriller = driller.Id, + DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), + DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified), + ShiftStart = new TimeDto(8, 0, 0), + ShiftEnd = new TimeDto(20, 0, 0), + } + }; + public ScheduleControllerTest(WebAppFactoryFixture factory) : base(factory, "api/schedule") { - var dbDriller = driller.Adapt(); - dbContext.Set().Add(dbDriller); - dbContext.SaveChanges(); - ExcludeProps.Add(nameof(ScheduleDto.Driller)); } @@ -155,5 +216,13 @@ namespace AsbCloudWebApi.IntegrationTests.Controllers dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(well.Timezone.Hours); return dto; } + + protected override Schedule Convert(ScheduleDto dto) + { + var entity = base.Convert(dto); + entity.DrillStart = dto.DrillStart.FromTimeZoneOffsetHours(well.Timezone.Hours); + entity.DrillEnd = dto.DrillEnd.FromTimeZoneOffsetHours(well.Timezone.Hours); + return entity; + } } } diff --git a/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs b/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs index 45219449..4142705c 100644 --- a/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs +++ b/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs @@ -10,8 +10,16 @@ namespace AsbCloudWebApi.IntegrationTests.Data new() { Id = 1, - Name = "test", - Surname = "test" + Name = "test1", + Surname = "test1", + Patronymic = "test1" + }, + new() + { + Id = 2, + Name = "test2", + Surname = "test2", + Patronymic = "test2" } }; From 8e720dc7c4e77ea76ad9b6a7bb220be36e2bcebc Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 27 Feb 2024 14:08:42 +0500 Subject: [PATCH 13/14] fix WellOperationExportServiceTest --- .../WellOperationExport/WellOperationExportServiceTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs index e58adda7..0c8523c4 100644 --- a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs @@ -118,7 +118,7 @@ namespace AsbCloudWebApi.Tests.Services.WellOperationExport wellOperationRepository = Substitute.For(); wellOperationCategoryRepository = Substitute.For(); wellOperationImportTemplateService = new WellOperationImportTemplateService(); - wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellService, wellOperationImportTemplateService, wellOperationCategoryRepository); + wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellOperationImportTemplateService, wellOperationCategoryRepository); wellOperationImportService = new WellOperationImportService(wellService, wellOperationRepository, wellOperationCategoryRepository); wellOperationDefaultExcelParser = new WellOperationDefaultExcelParser(); From f88c0ecd875e0ed9333ebf831e13b7d545ffc77b Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 28 Feb 2024 09:27:51 +0500 Subject: [PATCH 14/14] fix pipelines and publish profile --- .gitea/workflows/deploy-dev.yaml | 2 +- .gitea/workflows/deploy-prod.yaml | 2 +- .gitea/workflows/deploy.yaml | 2 +- .gitea/workflows/unit-tests.yaml | 2 +- AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/deploy-dev.yaml b/.gitea/workflows/deploy-dev.yaml index aab333d7..d263b21a 100644 --- a/.gitea/workflows/deploy-dev.yaml +++ b/.gitea/workflows/deploy-dev.yaml @@ -14,7 +14,7 @@ jobs: if: ${{ steps.cache-dotnet.outputs.cache-hit != 'true' }} uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.x - name: Check out repository code uses: actions/checkout@v4 - name: Add gitea as nuget source diff --git a/.gitea/workflows/deploy-prod.yaml b/.gitea/workflows/deploy-prod.yaml index a72f27b1..fc6cd3f6 100644 --- a/.gitea/workflows/deploy-prod.yaml +++ b/.gitea/workflows/deploy-prod.yaml @@ -14,7 +14,7 @@ jobs: if: ${{ steps.cache-dotnet.outputs.cache-hit != 'true' }} uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.x - name: Check out repository code uses: actions/checkout@v4 - name: Add gitea as nuget source diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml index 1879c4de..105d57c4 100644 --- a/.gitea/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -14,7 +14,7 @@ jobs: if: ${{ steps.cache-dotnet.outputs.cache-hit != 'true' }} uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.x - name: Check out repository code uses: actions/checkout@v4 - name: Add gitea as nuget source diff --git a/.gitea/workflows/unit-tests.yaml b/.gitea/workflows/unit-tests.yaml index 09711bfa..cd318b27 100644 --- a/.gitea/workflows/unit-tests.yaml +++ b/.gitea/workflows/unit-tests.yaml @@ -13,7 +13,7 @@ jobs: if: ${{ steps.cache-dotnet.outputs.cache-hit != 'true' }} uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.x - name: Check out repository code uses: actions/checkout@v4 - name: Add gitea as nuget source diff --git a/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml b/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml index 9ca6d0f0..c0b08b03 100644 --- a/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml +++ b/AsbCloudWebApi/Properties/PublishProfiles/PubLinux.pubxml @@ -13,7 +13,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. bin\publishLinux\ FileSystem - net6.0 + net8.0 a2768702-47cb-4127-941c-e339d5efcffe true linux-x64