diff --git a/AsbCloudApp/Data/DailyReport/HeadDto.cs b/AsbCloudApp/Data/DailyReport/HeadDto.cs
index e32dd63c..173d4e63 100644
--- a/AsbCloudApp/Data/DailyReport/HeadDto.cs
+++ b/AsbCloudApp/Data/DailyReport/HeadDto.cs
@@ -29,7 +29,7 @@ namespace AsbCloudApp.Data.DailyReport
///
/// дата рапорта
///
- public DateTime ReportDate { get; set; }
+ public DateOnly ReportDate { get; set; }
///
/// глубина забоя на дату начала интервала
diff --git a/AsbCloudApp/Services/IDailyReportService.cs b/AsbCloudApp/Services/IDailyReportService.cs
index 865985c0..67cfcc4e 100644
--- a/AsbCloudApp/Services/IDailyReportService.cs
+++ b/AsbCloudApp/Services/IDailyReportService.cs
@@ -20,7 +20,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task> GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken cancellationToken);
+ Task> GetListAsync(int idWell, DateOnly? begin, DateOnly? end, CancellationToken cancellationToken);
///
/// Добавить новый рапорт
@@ -30,7 +30,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task AddAsync(int idWell, DateTime startDate, int idUser, CancellationToken token);
+ Task AddAsync(int idWell, DateOnly startDate, int idUser, CancellationToken token);
///
/// Сформировать файл рапорта
@@ -39,7 +39,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task MakeReportAsync(int idWell, DateTime date, CancellationToken token);
+ Task MakeReportAsync(int idWell, DateOnly date, CancellationToken token);
///
/// изменить блок данных для суточного рапорта
@@ -49,6 +49,6 @@ namespace AsbCloudApp.Services
///
///
///
- Task UpdateBlockAsync(int idWell, DateTime startDate, ItemInfoDto dto, CancellationToken token);
+ Task UpdateBlockAsync(int idWell, DateOnly startDate, ItemInfoDto dto, CancellationToken token);
}
}
diff --git a/AsbCloudDb/EFExtentions.cs b/AsbCloudDb/EFExtentions.cs
index a00f2899..575480e3 100644
--- a/AsbCloudDb/EFExtentions.cs
+++ b/AsbCloudDb/EFExtentions.cs
@@ -5,6 +5,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
@@ -258,4 +260,17 @@ namespace AsbCloudDb
}
}
+ public class DateOnlyJsonConverter : JsonConverter
+ {
+ public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return DateOnly.FromDateTime(reader.GetDateTime());
+ }
+
+ public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
+ {
+ var isoDate = value.ToString("O");
+ writer.WriteStringValue(isoDate);
+ }
+ }
}
diff --git a/AsbCloudDb/Model/DailyReport/Head.cs b/AsbCloudDb/Model/DailyReport/Head.cs
index 42f6f857..fc5542e8 100644
--- a/AsbCloudDb/Model/DailyReport/Head.cs
+++ b/AsbCloudDb/Model/DailyReport/Head.cs
@@ -1,4 +1,6 @@
using System;
+using System.Text.Json.Serialization;
+
namespace AsbCloudDb.Model.DailyReport
{
public class Head : ItemInfo
@@ -26,7 +28,8 @@ namespace AsbCloudDb.Model.DailyReport
///
/// дата рапорта
///
- public DateTime ReportDate { get; set; }
+ [JsonConverter(typeof(DateOnlyJsonConverter))]
+ public DateOnly ReportDate { get; set; }
///
/// глубина забоя на дату начала интервала
diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
index 32853c0c..11be6762 100644
--- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
+++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
@@ -39,7 +39,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport
}
- public async Task> GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken token)
+ public async Task> GetListAsync(int idWell, DateOnly? begin, DateOnly? end, CancellationToken token)
{
var well = wellService.GetOrDefault(idWell);
if (well is null || well.Timezone is null)
@@ -49,14 +49,12 @@ namespace AsbCloudInfrastructure.Services.DailyReport
if (begin is not null)
{
- var beginDateOnly = ExtractDate(begin.Value, well);
- query = query.Where(d => d.StartDate >= beginDateOnly);
+ query = query.Where(d => d.StartDate >= begin);
}
if (end is not null)
{
- var endDateOnly = ExtractDate(end.Value, well);
- query = query.Where(d => d.StartDate <= endDateOnly);
+ query = query.Where(d => d.StartDate <= end);
}
var entities = await query.OrderByDescending(e => e.StartDate)
@@ -89,23 +87,22 @@ namespace AsbCloudInfrastructure.Services.DailyReport
return factOperations;
}
- public async Task AddAsync(int idWell, DateTime startDate, int idUser, CancellationToken token)
+ public async Task AddAsync(int idWell, DateOnly startDate, int idUser, CancellationToken token)
{
var well = wellService.GetOrDefault(idWell);
if (well is null)
throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell));
- var startDateOnly = ExtractDate(startDate, well);
var hasEntity = await db.DailyReports
- .AnyAsync(r => r.IdWell == idWell && r.StartDate == startDateOnly, token);
+ .AnyAsync(r => r.IdWell == idWell && r.StartDate == startDate, token);
if (hasEntity)
- throw new ArgumentInvalidException($"daily report on {startDateOnly} already exists", nameof(startDateOnly));
+ throw new ArgumentInvalidException($"daily report on {startDate} already exists", nameof(startDate));
var entity = new AsbCloudDb.Model.DailyReport.DailyReport
{
IdWell = idWell,
- StartDate = startDateOnly,
+ StartDate = startDate,
Info = new DailyReportInfo()
{
Head = CreateHeadDailyReportBlock(well, startDate, idUser)
@@ -116,14 +113,13 @@ namespace AsbCloudInfrastructure.Services.DailyReport
return result;
}
- public async Task UpdateBlockAsync(int idWell, DateTime startDate, ItemInfoDto dto, CancellationToken token)
+ public async Task UpdateBlockAsync(int idWell, DateOnly 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);
+ var entity = await db.DailyReports.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDate, token);
if (entity is null)
throw new ArgumentInvalidException("Daily report doesn`t exist", nameof(startDate));
@@ -145,7 +141,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport
return result;
}
- public async Task MakeReportAsync(int idWell, DateTime date, CancellationToken token)
+ public async Task MakeReportAsync(int idWell, DateOnly date, CancellationToken token)
{
var stageIds = WellOperationCategory.WorkStages.Select(w => w.Id).ToArray();
var wellOperationCategories = wellOperationRepository.GetCategories(true)
@@ -161,14 +157,10 @@ namespace AsbCloudInfrastructure.Services.DailyReport
return memoryStream;
}
- private async Task GetOrDefaultAsync(int idWell, DateTime date, CancellationToken token)
+ private async Task GetOrDefaultAsync(int idWell, DateOnly date, 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);
+ .FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == date, token);
if (entity is null)
throw new ArgumentInvalidException("Daily report doesn`t exist", nameof(date));
@@ -222,19 +214,6 @@ namespace AsbCloudInfrastructure.Services.DailyReport
return dto;
}
- ///
- /// Приведение данных к формату DateOnly с учетом часового пояса скважины
- ///
- ///
- ///
- ///
- private DateOnly ExtractDate(DateTime dateTime, WellDto well)
- {
- var dateTimeOffset = dateTime.ToUtcDateTimeOffset(well!.Timezone.Hours);
- var date = new DateOnly(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day);
- return date;
- }
-
///
/// Создание блока "Заголовок" по умолчанию
///
@@ -242,14 +221,14 @@ namespace AsbCloudInfrastructure.Services.DailyReport
///
///
///
- private Head CreateHeadDailyReportBlock(WellDto well, DateTime startDate, int idUser)
+ private Head CreateHeadDailyReportBlock(WellDto well, DateOnly 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,
+ ReportDate = startDate,
WellName = well.Caption,
ClusterName = well?.Cluster ?? string.Empty,
Customer = customer?.Caption ?? string.Empty,
diff --git a/AsbCloudWebApi/Controllers/DailyReportController.cs b/AsbCloudWebApi/Controllers/DailyReportController.cs
index 9f357e59..11183a4e 100644
--- a/AsbCloudWebApi/Controllers/DailyReportController.cs
+++ b/AsbCloudWebApi/Controllers/DailyReportController.cs
@@ -45,7 +45,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpGet]
[ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)]
- public async Task GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken token)
+ public async Task GetListAsync(int idWell, DateOnly? begin, DateOnly? end, CancellationToken token)
{
var result = await dailyReportService.GetListAsync(idWell, begin, end, token);
return Ok(result);
@@ -60,7 +60,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpPost]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
- public async Task AddAsync(int idWell, [Required] DateTime startDate, CancellationToken token)
+ public async Task AddAsync(int idWell, [Required] DateOnly startDate, CancellationToken token)
{
if (!await UserHasAccesToWellAsync(idWell, token))
return Forbid();
@@ -81,7 +81,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpPut("{date}/head")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
- public Task UpdateHeadAsync(int idWell, [Required] DateTime date, [Required] HeadDto dto, CancellationToken token)
+ public Task UpdateHeadAsync(int idWell, [Required] DateOnly date, [Required] HeadDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
///
@@ -94,7 +94,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpPut("{date}/bha")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
- public Task UpdateBhaAsync(int idWell, [Required] DateTime date, [Required] BhaDto dto, CancellationToken token)
+ public Task UpdateBhaAsync(int idWell, [Required] DateOnly date, [Required] BhaDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
///
@@ -107,7 +107,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpPut("{date}/noDrilling")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
- public Task UpdateNoDrillingAsync(int idWell, [Required] DateTime date, [Required] NoDrillingDto dto, CancellationToken token)
+ public Task UpdateNoDrillingAsync(int idWell, [Required] DateOnly date, [Required] NoDrillingDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
///
@@ -120,7 +120,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpPut("{date}/saub")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
- public Task UpdateSaubAsync(int idWell, [Required] DateTime date, [Required] SaubDto dto, CancellationToken token)
+ public Task UpdateSaubAsync(int idWell, [Required] DateOnly date, [Required] SaubDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
///
@@ -133,7 +133,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpPut("{date}/sign")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
- public Task UpdateSignAsync(int idWell, [Required] DateTime date, [Required] SignDto dto, CancellationToken token)
+ public Task UpdateSignAsync(int idWell, [Required] DateOnly date, [Required] SignDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
///
@@ -144,7 +144,7 @@ namespace AsbCloudWebApi.Controllers
///
///
///
- private async Task UpdateReportBlockAsync(int idWell, DateTime date, ItemInfoDto dto, CancellationToken token)
+ private async Task UpdateReportBlockAsync(int idWell, DateOnly date, ItemInfoDto dto, CancellationToken token)
{
if (!await UserHasAccesToWellAsync(idWell, token))
return Forbid();
@@ -165,7 +165,7 @@ namespace AsbCloudWebApi.Controllers
///
[HttpGet("{date}/excel")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
- public async Task DownloadAsync(int idWell, DateTime date, CancellationToken token)
+ public async Task DownloadAsync(int idWell, DateOnly date, CancellationToken token)
{
if (!await UserHasAccesToWellAsync(idWell, token))
return Forbid();
diff --git a/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs b/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs
new file mode 100644
index 00000000..df826075
--- /dev/null
+++ b/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs
@@ -0,0 +1,48 @@
+using System;
+using System.ComponentModel;
+using System.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace AsbCloudWebApi.Converters
+{
+#nullable enable
+ public class DateOnlyTypeConverter : TypeConverter
+ {
+ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+ {
+ if (sourceType == typeof(string))
+ {
+ return true;
+ }
+ return base.CanConvertFrom(context, sourceType);
+ }
+
+ public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+ {
+ if (value is string str)
+ {
+ return DateOnly.Parse(str);
+ }
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
+ {
+ if (destinationType == typeof(string))
+ {
+ return true;
+ }
+ return base.CanConvertTo(context, destinationType);
+ }
+ public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
+ {
+ if (destinationType == typeof(string) && value is DateOnly date)
+ {
+ return date.ToString("O");
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+#nullable disable
+}
diff --git a/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs b/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs
index 484d2f3e..ceb40b04 100644
--- a/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs
+++ b/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs
@@ -5,7 +5,7 @@ using System.Globalization;
namespace AsbCloudWebApi.Converters
{
#nullable enable
- public class DateOnlyTypeConverter : TypeConverter
+ public class TimeOnlyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{
diff --git a/AsbCloudWebApi/DependencyInjection.cs b/AsbCloudWebApi/DependencyInjection.cs
index f25a5494..25b66545 100644
--- a/AsbCloudWebApi/DependencyInjection.cs
+++ b/AsbCloudWebApi/DependencyInjection.cs
@@ -3,11 +3,9 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
-using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@@ -19,6 +17,7 @@ namespace AsbCloudWebApi
{
services.AddSwaggerGen(c =>
{
+ c.MapType(() => new OpenApiSchema { Type = "string", Format = "date" });
c.CustomOperationIds(e =>
{
return $"{e.ActionDescriptor.RouteValues["action"]}";
diff --git a/AsbCloudWebApi/Extentions.cs b/AsbCloudWebApi/Extentions.cs
index 1179c25e..aff16969 100644
--- a/AsbCloudWebApi/Extentions.cs
+++ b/AsbCloudWebApi/Extentions.cs
@@ -1,9 +1,10 @@
using AsbCloudApp.Data;
-using System.Collections.Generic;
-using System.Linq;
+using AsbCloudWebApi.Converters;
+using System;
+using System.ComponentModel;
using System.Security.Claims;
-namespace Microsoft.AspNetCore.Mvc
+namespace Microsoft.AspNetCore.Mvc
{
public static class Extentions
{
@@ -38,48 +39,12 @@ namespace Microsoft.AspNetCore.Mvc
});
}
- public static BadRequestBuilder BadRequestBuilder(this ControllerBase controller, string paramName, params string[] errors)
- => new BadRequestBuilder(paramName, errors);
- }
-
- public class BadRequestBuilder
- {
- private readonly Dictionary> body;
-
- private List GetOrCreateNew(string paramName)
+ public static MvcOptions UseDateOnlyTimeOnlyStringConverters(this MvcOptions options)
{
- List par;
- if (body.ContainsKey(paramName))
- par = body[paramName];
- else
- {
- par = new List();
- body[paramName] = par;
- }
- return par;
+ TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));
+ return options;
}
- public BadRequestBuilder(string paramName, params string[] errors)
- {
- body = new();
- body[paramName] = new List(errors);
- }
-
- public BadRequestBuilder Add(string paramName, params string[] errors)
- {
- var par = GetOrCreateNew(paramName);
- par.AddRange(errors);
- return this;
- }
-
- public BadRequestObjectResult Build()
- {
- var o = body.Select(e => new { name = e.Key, errors = e.Value.ToArray() });
-
- return new BadRequestObjectResult(o);
- }
-
- public static implicit operator BadRequestObjectResult(BadRequestBuilder d) => d.Build();
}
}
diff --git a/AsbCloudWebApi/Startup.cs b/AsbCloudWebApi/Startup.cs
index 96d408a5..14d8db0f 100644
--- a/AsbCloudWebApi/Startup.cs
+++ b/AsbCloudWebApi/Startup.cs
@@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi
{
@@ -31,6 +32,8 @@ namespace AsbCloudWebApi
}))
.AddProtoBufNet();
+ services.AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters());
+
ProtobufModel.EnshureRegistered();
services.AddSwagger();
@@ -90,6 +93,7 @@ namespace AsbCloudWebApi
});
});
+
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)