From 381557459b86d7e14fff9d6f699924612f64273e Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 25 Nov 2024 10:05:23 +0500 Subject: [PATCH 01/23] =?UTF-8?q?=D0=A7=D0=B5=D0=BD=D0=B4=D0=B6=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=20(=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20241122124437_AddChangeLog.Designer.cs | 152 ++++++++++++++++++ .../Migrations/20241122124437_AddChangeLog.cs | 39 +++++ .../PersistenceDbContextModelSnapshot.cs | 37 +++++ .../PersistenceDbContext.cs | 1 + .../Entity/ChangeLogAbstractData.cs | 53 ++++++ .../Entity/IChangeLogAbstractData.cs | 43 +++++ Persistence.Database/IPersistenceDbContext.cs | 1 + Persistence/Models/ChangeLogDto.cs | 29 ++-- ...ogAbstract.cs => IChangeLogAbstractDto.cs} | 30 +--- 9 files changed, 349 insertions(+), 36 deletions(-) create mode 100644 Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs create mode 100644 Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs create mode 100644 Persistence.Database/Entity/ChangeLogAbstractData.cs create mode 100644 Persistence.Database/Entity/IChangeLogAbstractData.cs rename Persistence/Models/{IChangeLogAbstract.cs => IChangeLogAbstractDto.cs} (53%) diff --git a/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs b/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs new file mode 100644 index 0000000..df89efd --- /dev/null +++ b/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs @@ -0,0 +1,152 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Persistence.Database.Model; + +#nullable disable + +namespace Persistence.Database.Postgres.Migrations +{ + [DbContext(typeof(PersistenceDbContext))] + [Migration("20241122124437_AddChangeLog")] + partial class AddChangeLog + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("Russian_Russia.1251") + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Persistence.Database.Model.ChangeLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("Id"); + + b.Property("Creation") + .HasColumnType("timestamp with time zone") + .HasColumnName("Creation"); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("IdAuthor"); + + b.Property("IdEditor") + .HasColumnType("integer") + .HasColumnName("IdEditor"); + + b.Property("IdNext") + .HasColumnType("integer") + .HasColumnName("IdNext"); + + b.Property("Obsolete") + .HasColumnType("timestamp with time zone") + .HasColumnName("Obsolete"); + + b.Property("Value") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.ToTable("ChangeLog"); + }); + + modelBuilder.Entity("Persistence.Database.Model.DataSaub", b => + { + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("AxialLoad") + .HasColumnType("double precision") + .HasColumnName("axialLoad"); + + b.Property("BitDepth") + .HasColumnType("double precision") + .HasColumnName("bitDepth"); + + b.Property("BlockPosition") + .HasColumnType("double precision") + .HasColumnName("blockPosition"); + + b.Property("BlockSpeed") + .HasColumnType("double precision") + .HasColumnName("blockSpeed"); + + b.Property("Flow") + .HasColumnType("double precision") + .HasColumnName("flow"); + + b.Property("HookWeight") + .HasColumnType("double precision") + .HasColumnName("hookWeight"); + + b.Property("IdFeedRegulator") + .HasColumnType("integer") + .HasColumnName("idFeedRegulator"); + + b.Property("Mode") + .HasColumnType("integer") + .HasColumnName("mode"); + + b.Property("Mse") + .HasColumnType("double precision") + .HasColumnName("mse"); + + b.Property("MseState") + .HasColumnType("smallint") + .HasColumnName("mseState"); + + b.Property("Pressure") + .HasColumnType("double precision") + .HasColumnName("pressure"); + + b.Property("Pump0Flow") + .HasColumnType("double precision") + .HasColumnName("pump0Flow"); + + b.Property("Pump1Flow") + .HasColumnType("double precision") + .HasColumnName("pump1Flow"); + + b.Property("Pump2Flow") + .HasColumnType("double precision") + .HasColumnName("pump2Flow"); + + b.Property("RotorSpeed") + .HasColumnType("double precision") + .HasColumnName("rotorSpeed"); + + b.Property("RotorTorque") + .HasColumnType("double precision") + .HasColumnName("rotorTorque"); + + b.Property("User") + .HasColumnType("text") + .HasColumnName("user"); + + b.Property("WellDepth") + .HasColumnType("double precision") + .HasColumnName("wellDepth"); + + b.HasKey("Date"); + + b.ToTable("DataSaub"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs b/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs new file mode 100644 index 0000000..70aad1d --- /dev/null +++ b/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs @@ -0,0 +1,39 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Persistence.Database.Postgres.Migrations +{ + /// + public partial class AddChangeLog : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ChangeLog", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + IdAuthor = table.Column(type: "integer", nullable: false), + IdEditor = table.Column(type: "integer", nullable: true), + Creation = table.Column(type: "timestamp with time zone", nullable: false), + Obsolete = table.Column(type: "timestamp with time zone", nullable: true), + IdNext = table.Column(type: "integer", nullable: true), + Value = table.Column(type: "jsonb", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChangeLog", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ChangeLog"); + } + } +} diff --git a/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs b/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs index 394c112..99dab9a 100644 --- a/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs +++ b/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs @@ -24,6 +24,43 @@ namespace Persistence.Database.Postgres.Migrations NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + modelBuilder.Entity("Persistence.Database.Model.ChangeLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("Id"); + + b.Property("Creation") + .HasColumnType("timestamp with time zone") + .HasColumnName("Creation"); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("IdAuthor"); + + b.Property("IdEditor") + .HasColumnType("integer") + .HasColumnName("IdEditor"); + + b.Property("IdNext") + .HasColumnType("integer") + .HasColumnName("IdNext"); + + b.Property("Obsolete") + .HasColumnType("timestamp with time zone") + .HasColumnName("Obsolete"); + + b.Property("Value") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("Value"); + + b.HasKey("Id"); + + b.ToTable("ChangeLog"); + }); + modelBuilder.Entity("Persistence.Database.Model.DataSaub", b => { b.Property("Date") diff --git a/Persistence.Database.Postgres/PersistenceDbContext.cs b/Persistence.Database.Postgres/PersistenceDbContext.cs index f68be73..097d3f3 100644 --- a/Persistence.Database.Postgres/PersistenceDbContext.cs +++ b/Persistence.Database.Postgres/PersistenceDbContext.cs @@ -5,6 +5,7 @@ namespace Persistence.Database.Model; public partial class PersistenceDbContext : DbContext, IPersistenceDbContext { public DbSet DataSaub => Set(); + public DbSet ChangeLog => Set(); public PersistenceDbContext() : base() diff --git a/Persistence.Database/Entity/ChangeLogAbstractData.cs b/Persistence.Database/Entity/ChangeLogAbstractData.cs new file mode 100644 index 0000000..ffc19c9 --- /dev/null +++ b/Persistence.Database/Entity/ChangeLogAbstractData.cs @@ -0,0 +1,53 @@ + +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; + +namespace Persistence.Database.Model; + +/// +/// Часть записи описывающая изменение +/// +public class ChangeLog : IChangeLogAbstractData +{ + /// + /// Ид записи + /// + [Key, Column("Id")] + public Guid Id { get; set; } + + /// + /// Автор изменения + /// + [Column("IdAuthor")] + public Guid IdAuthor { get; set; } + + /// + /// Редактор + /// + [Column("IdEditor")] + public Guid? IdEditor { get; set; } + + /// + /// Дата создания записи + /// + [Column("Creation")] + public DateTimeOffset Creation { get; set; } + + /// + /// Дата устаревания (например при удалении) + /// + [Column("Obsolete")] + public DateTimeOffset? Obsolete { get; set; } + + /// + /// Id заменяющей записи + /// + [Column("IdNext")] + public Guid? IdNext { get; set; } + + /// + /// Значение + /// + [Column("Value", TypeName = "jsonb")] + public required object Value { get; set; } +} diff --git a/Persistence.Database/Entity/IChangeLogAbstractData.cs b/Persistence.Database/Entity/IChangeLogAbstractData.cs new file mode 100644 index 0000000..750fef4 --- /dev/null +++ b/Persistence.Database/Entity/IChangeLogAbstractData.cs @@ -0,0 +1,43 @@ + +namespace Persistence.Database.Model; + +/// +/// Часть записи описывающая изменение +/// +public interface IChangeLogAbstractData +{ + /// + /// Ид записи + /// + public Guid Id { get; set; } + + /// + /// Автор изменения + /// + public int IdAuthor { get; set; } + + /// + /// Редактор + /// + public int? IdEditor { get; set; } + + /// + /// Дата создания записи + /// + public DateTimeOffset Creation { get; set; } + + /// + /// Дата устаревания (например при удалении) + /// + public DateTimeOffset? Obsolete { get; set; } + + /// + /// Id заменяющей записи + /// + public int? IdNext { get; set; } + + /// + /// Значение + /// + public object Value { get; set; } +} diff --git a/Persistence.Database/IPersistenceDbContext.cs b/Persistence.Database/IPersistenceDbContext.cs index 66f34ff..0837294 100644 --- a/Persistence.Database/IPersistenceDbContext.cs +++ b/Persistence.Database/IPersistenceDbContext.cs @@ -5,4 +5,5 @@ namespace Persistence.Database; public interface IPersistenceDbContext : IDisposable { DbSet DataSaub { get; } + DbSet ChangeLog { get; } } diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index 6b2a090..d9acc66 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -1,9 +1,11 @@ + namespace Persistence.Models; /// /// Часть записи описывающая изменение /// -public class ChangeLogDto where T: class +public class ChangeLogDto : IChangeLogAbstractDto + where T: class { /// /// Запись @@ -11,32 +13,37 @@ public class ChangeLogDto where T: class public required T Item { get; set; } /// - /// Автор + /// /// - public UserDto? Author { get; set; } + public int Id { get; set; } /// - /// Автор + /// /// - public UserDto? Editor { get; set; } + public int IdAuthor { get; set; } /// - /// Дата создания записи + /// + /// + public int? IdEditor { get; set; } + + /// + /// /// public DateTimeOffset Creation { get; set; } /// - /// Дата устаревания (например, при удалении) + /// /// public DateTimeOffset? Obsolete { get; set; } /// - /// Id состояния + /// /// - public int IdState { get; set; } + public int? IdNext { get; set; } /// - /// Id заменяемой записи + /// /// - public int? IdPrevious { get; set; } + public required object Value { get; set; } } diff --git a/Persistence/Models/IChangeLogAbstract.cs b/Persistence/Models/IChangeLogAbstractDto.cs similarity index 53% rename from Persistence/Models/IChangeLogAbstract.cs rename to Persistence/Models/IChangeLogAbstractDto.cs index a23ab1b..b9fd209 100644 --- a/Persistence/Models/IChangeLogAbstract.cs +++ b/Persistence/Models/IChangeLogAbstractDto.cs @@ -3,28 +3,8 @@ /// /// Часть записи описывающая изменение /// -public interface IChangeLogAbstract +public interface IChangeLogAbstractDto { - /// - /// Актуальная - /// - public const int IdStateActual = 0; - - /// - /// Замененная - /// - public const int IdStateReplaced = 1; - - /// - /// Удаленная - /// - public const int IdStateDeleted = 2; - - /// - /// Очищено при импорте - /// - public const int IdCleared = 3; - /// /// Ид записи /// @@ -51,12 +31,12 @@ public interface IChangeLogAbstract public DateTimeOffset? Obsolete { get; set; } /// - /// "ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная + /// Id заменяющей записи /// - public int IdState { get; set; } + public int? IdNext { get; set; } /// - /// Id заменяемой записи + /// Значение /// - public int? IdPrevious { get; set; } + public object Value { get; set; } } -- 2.45.2 From d7b5b7e3ab7ba446a2797d692c3ff0ead88abb96 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 25 Nov 2024 18:11:46 +0500 Subject: [PATCH 02/23] =?UTF-8?q?=D0=A7=D0=B5=D0=BD=D0=B4=D0=B6=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=20(=D0=BF=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 61 +++++++++++++++++ ...{ChangeLogAbstractData.cs => ChangeLog.cs} | 10 ++- .../ChangeLogWithWellDepthAndSectionId.cs | 29 ++++++++ ...ChangeLogAbstractData.cs => IChangeLog.cs} | 8 +-- .../Repositories/ChangeLogRepository.cs | 68 +++++++++++++++++++ Persistence/Models/ChangeLogDto.cs | 2 +- Persistence/Models/IChangeLogAbstractDto.cs | 42 ------------ Persistence/Models/IChangeLogDto.cs | 42 ++++++++++++ Persistence/Models/ProcessMapRotorDto.cs | 11 +++ .../Repositories/IChangeLogRepository.cs | 2 +- 10 files changed, 225 insertions(+), 50 deletions(-) create mode 100644 Persistence.API/Controllers/ChangeLogController.cs rename Persistence.Database/Entity/{ChangeLogAbstractData.cs => ChangeLog.cs} (81%) create mode 100644 Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs rename Persistence.Database/Entity/{IChangeLogAbstractData.cs => IChangeLog.cs} (84%) create mode 100644 Persistence.Repository/Repositories/ChangeLogRepository.cs delete mode 100644 Persistence/Models/IChangeLogAbstractDto.cs create mode 100644 Persistence/Models/IChangeLogDto.cs create mode 100644 Persistence/Models/ProcessMapRotorDto.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs new file mode 100644 index 0000000..b982382 --- /dev/null +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -0,0 +1,61 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Persistence.Database.Model; +using Persistence.Models; +using Persistence.Repositories; + +namespace Persistence.API.Controllers; + +[ApiController] +[Authorize] +[Route("api/[controller]")] +public class ChangeLogRotorController : ControllerBase, IChangeLogApi> +{ + private IChangeLogRepository> repository; + + public ChangeLogRotorController(IChangeLogRepository> repository) + { + this.repository = repository; + } + public async Task> Add(ProcessMapRotorDto dto, CancellationToken token) + { + await repository.InsertRange(0, [dto], token); + + return null; + } + + public Task> AddRange(IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> Delete(int id, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> DeleteRange(IEnumerable ids, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task>> GetChangeLogCurrent(CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> Update(ProcessMapRotorDto dto, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> UpdateRange(IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } +} diff --git a/Persistence.Database/Entity/ChangeLogAbstractData.cs b/Persistence.Database/Entity/ChangeLog.cs similarity index 81% rename from Persistence.Database/Entity/ChangeLogAbstractData.cs rename to Persistence.Database/Entity/ChangeLog.cs index ffc19c9..f25f61b 100644 --- a/Persistence.Database/Entity/ChangeLogAbstractData.cs +++ b/Persistence.Database/Entity/ChangeLog.cs @@ -5,9 +5,9 @@ using System.ComponentModel.DataAnnotations; namespace Persistence.Database.Model; /// -/// Часть записи описывающая изменение +/// Часть записи, описывающая изменение /// -public class ChangeLog : IChangeLogAbstractData +public class ChangeLog : IChangeLog { /// /// Ид записи @@ -15,6 +15,12 @@ public class ChangeLog : IChangeLogAbstractData [Key, Column("Id")] public Guid Id { get; set; } + /// + /// Дискриминатор таблицы + /// + [Column("IdDiscriminator")] + public Guid IdDiscriminator { get; set; } + /// /// Автор изменения /// diff --git a/Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs b/Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs new file mode 100644 index 0000000..abbe58f --- /dev/null +++ b/Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs @@ -0,0 +1,29 @@ + +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; + +namespace Persistence.Database.Model; + +/// +/// Часть записи, описывающая изменение данных, содержащие начальную и конечную глубину, а также секцию +/// +public class ChangeLogWithWellDepthAndSectionId : ChangeLog +{ + /// + /// Глубина забоя на дату начала интервала + /// + [Column("DepthStart")] + public double? DepthStart { get; set; } + + /// + /// Глубина забоя на дату окончания интервала + /// + [Column("DepthEnd")] + public double? DepthEnd { get; set; } + + /// + /// Ключ секции + /// + [Column("IdSection")] + public Guid IdSection { get; set; } +} diff --git a/Persistence.Database/Entity/IChangeLogAbstractData.cs b/Persistence.Database/Entity/IChangeLog.cs similarity index 84% rename from Persistence.Database/Entity/IChangeLogAbstractData.cs rename to Persistence.Database/Entity/IChangeLog.cs index 750fef4..f8a5b15 100644 --- a/Persistence.Database/Entity/IChangeLogAbstractData.cs +++ b/Persistence.Database/Entity/IChangeLog.cs @@ -4,7 +4,7 @@ namespace Persistence.Database.Model; /// /// Часть записи описывающая изменение /// -public interface IChangeLogAbstractData +public interface IChangeLog { /// /// Ид записи @@ -14,12 +14,12 @@ public interface IChangeLogAbstractData /// /// Автор изменения /// - public int IdAuthor { get; set; } + public Guid IdAuthor { get; set; } /// /// Редактор /// - public int? IdEditor { get; set; } + public Guid? IdEditor { get; set; } /// /// Дата создания записи @@ -34,7 +34,7 @@ public interface IChangeLogAbstractData /// /// Id заменяющей записи /// - public int? IdNext { get; set; } + public Guid? IdNext { get; set; } /// /// Значение diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs new file mode 100644 index 0000000..046e2bd --- /dev/null +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -0,0 +1,68 @@ +using Mapster; +using Microsoft.EntityFrameworkCore; +using Persistence.Database.Model; +using Persistence.Models; +using Persistence.Repositories; + +namespace Persistence.Repository.Repositories; +public class ChangeLogRepository : IChangeLogRepository + where TDto : class, IChangeLogDto, new() + where TChangeLogDto : ChangeLogDto +{ + private DbContext db; + + public ChangeLogRepository(DbContext db) + { + this.db = db; + } + + public Task Clear(int idUser, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task ClearAndInsertRange(int idUser, IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> GetCurrent(DateTimeOffset moment, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> GetDatesChange(CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task> GetGtDate(DateTimeOffset dateBegin, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task InsertRange(int idUser, IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task MarkAsDeleted(int idUser, IEnumerable ids, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task UpdateOrInsertRange(int idUser, IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task UpdateRange(int idUser, IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } +} diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index d9acc66..14e937b 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -4,7 +4,7 @@ namespace Persistence.Models; /// /// Часть записи описывающая изменение /// -public class ChangeLogDto : IChangeLogAbstractDto +public class ChangeLogDto : IChangeLogDto where T: class { /// diff --git a/Persistence/Models/IChangeLogAbstractDto.cs b/Persistence/Models/IChangeLogAbstractDto.cs deleted file mode 100644 index b9fd209..0000000 --- a/Persistence/Models/IChangeLogAbstractDto.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Persistence.Models; - -/// -/// Часть записи описывающая изменение -/// -public interface IChangeLogAbstractDto -{ - /// - /// Ид записи - /// - public int Id { get; set; } - - /// - /// Автор изменения - /// - public int IdAuthor { get; set; } - - /// - /// Редактор - /// - public int? IdEditor { get; set; } - - /// - /// Дата создания записи - /// - public DateTimeOffset Creation { get; set; } - - /// - /// Дата устаревания (например при удалении) - /// - public DateTimeOffset? Obsolete { get; set; } - - /// - /// Id заменяющей записи - /// - public int? IdNext { get; set; } - - /// - /// Значение - /// - public object Value { get; set; } -} diff --git a/Persistence/Models/IChangeLogDto.cs b/Persistence/Models/IChangeLogDto.cs new file mode 100644 index 0000000..09cfd09 --- /dev/null +++ b/Persistence/Models/IChangeLogDto.cs @@ -0,0 +1,42 @@ +namespace Persistence.Models; + +/// +/// Часть записи описывающая изменение +/// +public interface IChangeLogDto +{ + ///// + ///// Ид записи + ///// + //public int Id { get; set; } + + ///// + ///// Автор изменения + ///// + //public int IdAuthor { get; set; } + + ///// + ///// Редактор + ///// + //public int? IdEditor { get; set; } + + ///// + ///// Дата создания записи + ///// + //public DateTimeOffset Creation { get; set; } + + ///// + ///// Дата устаревания (например при удалении) + ///// + //public DateTimeOffset? Obsolete { get; set; } + + ///// + ///// Id заменяющей записи + ///// + //public int? IdNext { get; set; } + + ///// + ///// Значение + ///// + //public object Value { get; set; } +} diff --git a/Persistence/Models/ProcessMapRotorDto.cs b/Persistence/Models/ProcessMapRotorDto.cs new file mode 100644 index 0000000..316f07a --- /dev/null +++ b/Persistence/Models/ProcessMapRotorDto.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Persistence.Models; +public class ProcessMapRotorDto : IChangeLogDto +{ + public string Caption { get; set; } +} diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index c12c61b..3435ee1 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -7,7 +7,7 @@ namespace Persistence.Repositories; /// /// public interface IChangeLogRepository : ISyncRepository - where TDto : class, ITimeSeriesAbstractDto, new() + where TDto : class, IChangeLogDto, new() where TChangeLogDto : ChangeLogDto { /// -- 2.45.2 From 24046d85056826ee6e73f14eb07f606a85a96d14 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Tue, 26 Nov 2024 10:32:44 +0500 Subject: [PATCH 03/23] =?UTF-8?q?=D0=A7=D0=B5=D0=BD=D0=B4=D0=B6=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=20(=D0=BD=D0=B0=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 35 ++++++++++++------- Persistence.Repository/DependencyInjection.cs | 2 ++ .../Repositories/ChangeLogRepository.cs | 16 +++++++-- Persistence/API/IChangeLogApi.cs | 2 +- Persistence/Models/ChangeLogDto.cs | 2 +- .../Repositories/IChangeLogRepository.cs | 2 +- 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index b982382..6060faa 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -9,52 +9,63 @@ namespace Persistence.API.Controllers; [ApiController] [Authorize] [Route("api/[controller]")] -public class ChangeLogRotorController : ControllerBase, IChangeLogApi> +public class ChangeLogController : ControllerBase, IChangeLogApi> + where TDto : class, IChangeLogDto, new() { - private IChangeLogRepository> repository; + private IChangeLogRepository> repository; - public ChangeLogRotorController(IChangeLogRepository> repository) + public ChangeLogController(IChangeLogRepository> repository) { this.repository = repository; } - public async Task> Add(ProcessMapRotorDto dto, CancellationToken token) - { - await repository.InsertRange(0, [dto], token); - return null; + [HttpPost] + public async Task> Add(TDto dto, CancellationToken token) + { + var userId = User.GetUserId(); + var result = await repository.InsertRange(userId, [dto], token); + + return Ok(result); } - public Task> AddRange(IEnumerable dtos, CancellationToken token) + [HttpPost("range")] + public Task> AddRange(IEnumerable dtos, CancellationToken token) { throw new NotImplementedException(); } + [HttpDelete] public Task> Delete(int id, CancellationToken token) { throw new NotImplementedException(); } + [HttpDelete("range")] public Task> DeleteRange(IEnumerable ids, CancellationToken token) { throw new NotImplementedException(); } - public Task>> GetChangeLogCurrent(CancellationToken token) + [HttpGet] + public Task>> GetChangeLogCurrent(CancellationToken token) { throw new NotImplementedException(); } - public Task>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) + [HttpGet("history")] + public Task>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) { throw new NotImplementedException(); } - public Task> Update(ProcessMapRotorDto dto, CancellationToken token) + [HttpPut] + public Task> Update(TDto dto, CancellationToken token) { throw new NotImplementedException(); } - public Task> UpdateRange(IEnumerable dtos, CancellationToken token) + [HttpPut("range")] + public Task> UpdateRange(IEnumerable dtos, CancellationToken token) { throw new NotImplementedException(); } diff --git a/Persistence.Repository/DependencyInjection.cs b/Persistence.Repository/DependencyInjection.cs index 8e2f759..d732434 100644 --- a/Persistence.Repository/DependencyInjection.cs +++ b/Persistence.Repository/DependencyInjection.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Persistence.Database.Model; +using Persistence.Models; using Persistence.Repositories; using Persistence.Repository.Data; using Persistence.Repository.Repositories; @@ -16,6 +17,7 @@ public static class DependencyInjection MapsterSetup(); services.AddTransient, TimeSeriesDataCachedRepository>(); + services.AddTransient(typeof(IChangeLogRepository<,>), typeof(ChangeLogRepository<,>)); return services; } diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 046e2bd..9195788 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -46,9 +46,21 @@ public class ChangeLogRepository : IChangeLogRepository InsertRange(int idUser, IEnumerable dtos, CancellationToken token) + public Task InsertRange(Guid idUser, IEnumerable dtos, CancellationToken token) { - throw new NotImplementedException(); + var entity = new ChangeLog() { + Value = dtos, + Creation = DateTimeOffset.UtcNow, + Id = idUser, + IdAuthor = idUser, + IdDiscriminator = new Guid(), + IdEditor = idUser + }; + entity.Id = idUser; + + db.Set().Add(entity); + var result = db.SaveChangesAsync(token); + return result; } public Task MarkAsDeleted(int idUser, IEnumerable ids, CancellationToken token) diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index bb4a3c3..2a734ca 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -7,7 +7,7 @@ namespace Persistence.API; /// Интерфейс для работы с API журнала изменений /// public interface IChangeLogApi - where TDto : class, new() + where TDto : class, IChangeLogDto, new() where TChangeLogDto : ChangeLogDto { /// diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index 14e937b..deb0c2b 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -5,7 +5,7 @@ namespace Persistence.Models; /// Часть записи описывающая изменение /// public class ChangeLogDto : IChangeLogDto - where T: class + where T: class, IChangeLogDto, new() { /// /// Запись diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index 3435ee1..5e05652 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -17,7 +17,7 @@ public interface IChangeLogRepository : ISyncRepository /// /// - Task InsertRange(int idUser, IEnumerable dtos, CancellationToken token); + Task InsertRange(Guid idUser, IEnumerable dtos, CancellationToken token); /// /// Редактирование записей -- 2.45.2 From 44730bb66e5c5f5258f5c54edc95ab53ca080752 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Tue, 26 Nov 2024 11:47:42 +0500 Subject: [PATCH 04/23] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=B6=D0=B5=D0=BD=D0=B5=D1=80=D0=B8=D0=BA=D0=B8=20=D1=83?= =?UTF-8?q?=20=D0=B2=D1=81=D0=B5=D0=B3=D0=BE,=20=D1=87=D1=82=D0=BE=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=81=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20changeLog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 31 ++++++++----- Persistence.Database/Entity/ChangeLog.cs | 4 +- Persistence.Database/Entity/IChangeLog.cs | 11 ++++- Persistence.Repository/DependencyInjection.cs | 2 +- .../Repositories/ChangeLogRepository.cs | 45 ++++++++++--------- Persistence/API/IChangeLogApi.cs | 16 +++---- Persistence/Models/ChangeLogDto.cs | 26 ++++++----- .../Repositories/IChangeLogRepository.cs | 17 ++++--- 8 files changed, 86 insertions(+), 66 deletions(-) diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 6060faa..de0ef2f 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -9,27 +9,29 @@ namespace Persistence.API.Controllers; [ApiController] [Authorize] [Route("api/[controller]")] -public class ChangeLogController : ControllerBase, IChangeLogApi> - where TDto : class, IChangeLogDto, new() +public class ChangeLogController : ControllerBase, IChangeLogApi { - private IChangeLogRepository> repository; + private IChangeLogRepository repository; - public ChangeLogController(IChangeLogRepository> repository) + public ChangeLogController(IChangeLogRepository repository) { this.repository = repository; } [HttpPost] - public async Task> Add(TDto dto, CancellationToken token) + public async Task> Add( + [FromRoute] Guid idDiscriminator, + [FromBody]IDictionary dtos, + CancellationToken token) { var userId = User.GetUserId(); - var result = await repository.InsertRange(userId, [dto], token); + var result = await repository.InsertRange(userId, idDiscriminator, [dtos], token); return Ok(result); } [HttpPost("range")] - public Task> AddRange(IEnumerable dtos, CancellationToken token) + public Task> AddRange(IEnumerable> dtos, CancellationToken token) { throw new NotImplementedException(); } @@ -47,25 +49,30 @@ public class ChangeLogController : ControllerBase, IChangeLogApi>> GetChangeLogCurrent(CancellationToken token) + public Task>>> GetChangeLogCurrent(CancellationToken token) { throw new NotImplementedException(); } - [HttpGet("history")] - public Task>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) + public Task>>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) { throw new NotImplementedException(); } + //[HttpGet("history")] + //public Task>>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) + //{ + // throw new NotImplementedException(); + //} + [HttpPut] - public Task> Update(TDto dto, CancellationToken token) + public Task> Update(IDictionary dto, CancellationToken token) { throw new NotImplementedException(); } [HttpPut("range")] - public Task> UpdateRange(IEnumerable dtos, CancellationToken token) + public Task> UpdateRange(IEnumerable> dtos, CancellationToken token) { throw new NotImplementedException(); } diff --git a/Persistence.Database/Entity/ChangeLog.cs b/Persistence.Database/Entity/ChangeLog.cs index f25f61b..59802ae 100644 --- a/Persistence.Database/Entity/ChangeLog.cs +++ b/Persistence.Database/Entity/ChangeLog.cs @@ -10,7 +10,7 @@ namespace Persistence.Database.Model; public class ChangeLog : IChangeLog { /// - /// Ид записи + /// Ключ записи /// [Key, Column("Id")] public Guid Id { get; set; } @@ -55,5 +55,5 @@ public class ChangeLog : IChangeLog /// Значение /// [Column("Value", TypeName = "jsonb")] - public required object Value { get; set; } + public required IDictionary Value { get; set; } } diff --git a/Persistence.Database/Entity/IChangeLog.cs b/Persistence.Database/Entity/IChangeLog.cs index f8a5b15..449c691 100644 --- a/Persistence.Database/Entity/IChangeLog.cs +++ b/Persistence.Database/Entity/IChangeLog.cs @@ -1,4 +1,6 @@  +using System.ComponentModel.DataAnnotations.Schema; + namespace Persistence.Database.Model; /// @@ -7,7 +9,7 @@ namespace Persistence.Database.Model; public interface IChangeLog { /// - /// Ид записи + /// Ключ записи /// public Guid Id { get; set; } @@ -36,8 +38,13 @@ public interface IChangeLog /// public Guid? IdNext { get; set; } + /// + /// Дискриминатор таблицы + /// + public Guid IdDiscriminator { get; set; } + /// /// Значение /// - public object Value { get; set; } + public IDictionary Value { get; set; } } diff --git a/Persistence.Repository/DependencyInjection.cs b/Persistence.Repository/DependencyInjection.cs index d732434..34c47f4 100644 --- a/Persistence.Repository/DependencyInjection.cs +++ b/Persistence.Repository/DependencyInjection.cs @@ -17,7 +17,7 @@ public static class DependencyInjection MapsterSetup(); services.AddTransient, TimeSeriesDataCachedRepository>(); - services.AddTransient(typeof(IChangeLogRepository<,>), typeof(ChangeLogRepository<,>)); + services.AddTransient(); return services; } diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 9195788..f0d8141 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -5,9 +5,7 @@ using Persistence.Models; using Persistence.Repositories; namespace Persistence.Repository.Repositories; -public class ChangeLogRepository : IChangeLogRepository - where TDto : class, IChangeLogDto, new() - where TChangeLogDto : ChangeLogDto +public class ChangeLogRepository : IChangeLogRepository { private DbContext db; @@ -21,17 +19,17 @@ public class ChangeLogRepository : IChangeLogRepository ClearAndInsertRange(int idUser, IEnumerable dtos, CancellationToken token) + public Task ClearAndInsertRange(int idUser, IEnumerable> dtos, CancellationToken token) { throw new NotImplementedException(); } - public Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) + public Task>>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) { throw new NotImplementedException(); } - public Task> GetCurrent(DateTimeOffset moment, CancellationToken token) + public Task>> GetCurrent(DateTimeOffset moment, CancellationToken token) { throw new NotImplementedException(); } @@ -41,25 +39,32 @@ public class ChangeLogRepository : IChangeLogRepository> GetGtDate(DateTimeOffset dateBegin, CancellationToken token) + public Task>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token) { throw new NotImplementedException(); } - public Task InsertRange(Guid idUser, IEnumerable dtos, CancellationToken token) + public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable> dtos, CancellationToken token) { - var entity = new ChangeLog() { - Value = dtos, - Creation = DateTimeOffset.UtcNow, - Id = idUser, - IdAuthor = idUser, - IdDiscriminator = new Guid(), - IdEditor = idUser - }; - entity.Id = idUser; + var entities = new List(); + foreach (var dto in dtos) + { + var entity = new ChangeLog() + { + IdAuthor = idUser, + IdDiscriminator = idDiscriminator, + IdEditor = idUser, + Value = dto, + Creation = DateTimeOffset.UtcNow + }; + entity.Id = idUser; - db.Set().Add(entity); + entities.Add(entity); + } + + db.Set().AddRange(entities); var result = db.SaveChangesAsync(token); + return result; } @@ -68,12 +73,12 @@ public class ChangeLogRepository : IChangeLogRepository UpdateOrInsertRange(int idUser, IEnumerable dtos, CancellationToken token) + public Task UpdateOrInsertRange(int idUser, IEnumerable> dtos, CancellationToken token) { throw new NotImplementedException(); } - public Task UpdateRange(int idUser, IEnumerable dtos, CancellationToken token) + public Task UpdateRange(int idUser, IEnumerable> dtos, CancellationToken token) { throw new NotImplementedException(); } diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index 2a734ca..6cb0896 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -6,16 +6,14 @@ namespace Persistence.API; /// /// Интерфейс для работы с API журнала изменений /// -public interface IChangeLogApi - where TDto : class, IChangeLogDto, new() - where TChangeLogDto : ChangeLogDto +public interface IChangeLogApi { /// /// Получение исторических данных на текущую дату /// /// /// - Task>> GetChangeLogCurrent(CancellationToken token); + Task>>> GetChangeLogCurrent(CancellationToken token); /// /// Получение исторических данных на определенную дату @@ -23,7 +21,7 @@ public interface IChangeLogApi /// /// /// - Task>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token); + Task>>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token); /// /// Добавить одну запись @@ -31,7 +29,7 @@ public interface IChangeLogApi /// /// /// - Task> Add(TDto dto, CancellationToken token); + Task> Add(Guid idDiscriminator, IDictionary dto, CancellationToken token); /// /// Добавить несколько записей @@ -39,7 +37,7 @@ public interface IChangeLogApi /// /// /// - Task> AddRange(IEnumerable dtos, CancellationToken token); + Task> AddRange(IEnumerable> dtos, CancellationToken token); /// /// Обновить одну запись @@ -47,7 +45,7 @@ public interface IChangeLogApi /// /// /// - Task> Update(TDto dto, CancellationToken token); + Task> Update(IDictionary dto, CancellationToken token); /// /// Обновить несколько записей @@ -55,7 +53,7 @@ public interface IChangeLogApi /// /// /// - Task> UpdateRange(IEnumerable dtos, CancellationToken token); + Task> UpdateRange(IEnumerable> dtos, CancellationToken token); /// /// Удалить одну запись diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index deb0c2b..8f716f4 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -5,8 +5,12 @@ namespace Persistence.Models; /// Часть записи описывающая изменение /// public class ChangeLogDto : IChangeLogDto - where T: class, IChangeLogDto, new() + where T: IDictionary { + public ChangeLogDto() + { + + } /// /// Запись /// @@ -15,35 +19,35 @@ public class ChangeLogDto : IChangeLogDto /// /// /// - public int Id { get; set; } + public Guid Id { get; set; } /// - /// + /// Создатель записи /// - public int IdAuthor { get; set; } + public Guid IdAuthor { get; set; } /// - /// + /// Пользователь, изменивший запись /// - public int? IdEditor { get; set; } + public Guid? IdEditor { get; set; } /// - /// + /// Дата создания /// public DateTimeOffset Creation { get; set; } /// - /// + /// Дата устаревания /// public DateTimeOffset? Obsolete { get; set; } /// - /// + /// Ключ следующей записи /// - public int? IdNext { get; set; } + public Guid? IdNext { get; set; } /// - /// + /// Объект записи /// public required object Value { get; set; } } diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index 5e05652..06fbeb2 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -6,18 +6,17 @@ namespace Persistence.Repositories; /// Интерфейс для работы с историческими данными /// /// -public interface IChangeLogRepository : ISyncRepository - where TDto : class, IChangeLogDto, new() - where TChangeLogDto : ChangeLogDto +public interface IChangeLogRepository //: ISyncRepository { /// /// Добавление записей /// /// пользователь, который добавляет + /// ключ справочника /// /// /// - Task InsertRange(Guid idUser, IEnumerable dtos, CancellationToken token); + Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable> dtos, CancellationToken token); /// /// Редактирование записей @@ -26,7 +25,7 @@ public interface IChangeLogRepository : ISyncRepository /// /// - Task UpdateRange(int idUser, IEnumerable dtos, CancellationToken token); + Task UpdateRange(int idUser, IEnumerable> dtos, CancellationToken token); /// /// Добавляет Dto у которых id == 0, изменяет dto у которых id != 0 @@ -35,7 +34,7 @@ public interface IChangeLogRepository : ISyncRepository /// /// - Task UpdateOrInsertRange(int idUser, IEnumerable dtos, CancellationToken token); + Task UpdateOrInsertRange(int idUser, IEnumerable> dtos, CancellationToken token); /// /// Помечает записи как удаленные @@ -52,7 +51,7 @@ public interface IChangeLogRepository : ISyncRepository /// /// - Task ClearAndInsertRange(int idUser, IEnumerable dtos, CancellationToken token); + Task ClearAndInsertRange(int idUser, IEnumerable> dtos, CancellationToken token); /// /// Пометить записи как удаленные @@ -77,7 +76,7 @@ public interface IChangeLogRepository : ISyncRepository /// /// - Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token); + Task>>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token); /// /// Получение текущих сейчас записей по параметрам @@ -85,5 +84,5 @@ public interface IChangeLogRepository : ISyncRepository /// /// - Task> GetCurrent(DateTimeOffset moment, CancellationToken token); + Task>> GetCurrent(DateTimeOffset moment, CancellationToken token); } -- 2.45.2 From c5645df2e6e47eb5f514672ca2469430418cf290 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Tue, 26 Nov 2024 14:19:16 +0500 Subject: [PATCH 05/23] =?UTF-8?q?=D0=9C=D0=B5=D1=82=D0=BE=D0=B4=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20change?= =?UTF-8?q?Log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 9 ++--- .../DependencyInjection.cs | 9 +++-- ... 20241126071115_Add_ChangeLog.Designer.cs} | 35 ++++++++++++++----- ...Log.cs => 20241126071115_Add_ChangeLog.cs} | 15 +++++--- .../PersistenceDbContextModelSnapshot.cs | 31 ++++++++++++---- Persistence.Database.Postgres/Readme.md | 8 ++++- Persistence.Database/Entity/ChangeLog.cs | 18 ++++++++++ .../ChangeLogWithWellDepthAndSectionId.cs | 29 --------------- Persistence.Database/Entity/IChangeLog.cs | 2 +- .../Repositories/ChangeLogRepository.cs | 11 +++--- Persistence/API/IChangeLogApi.cs | 4 +-- Persistence/Models/ChangeLogDto.cs | 27 +++++++++----- .../Repositories/IChangeLogRepository.cs | 4 +-- 13 files changed, 127 insertions(+), 75 deletions(-) rename Persistence.Database.Postgres/Migrations/{20241122124437_AddChangeLog.Designer.cs => 20241126071115_Add_ChangeLog.Designer.cs} (82%) rename Persistence.Database.Postgres/Migrations/{20241122124437_AddChangeLog.cs => 20241126071115_Add_ChangeLog.cs} (58%) delete mode 100644 Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index de0ef2f..dd92e04 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -20,12 +20,12 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpPost] public async Task> Add( - [FromRoute] Guid idDiscriminator, - [FromBody]IDictionary dtos, + [FromRoute] Guid idDiscriminator, + ChangeLogDto dto, CancellationToken token) { var userId = User.GetUserId(); - var result = await repository.InsertRange(userId, idDiscriminator, [dtos], token); + var result = await repository.InsertRange(userId, idDiscriminator, [dto], token); return Ok(result); } @@ -54,7 +54,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi throw new NotImplementedException(); } - public Task>>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) + [HttpGet("history")] + public Task>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) { throw new NotImplementedException(); } diff --git a/Persistence.Database.Postgres/DependencyInjection.cs b/Persistence.Database.Postgres/DependencyInjection.cs index 3acd55c..0fec635 100644 --- a/Persistence.Database.Postgres/DependencyInjection.cs +++ b/Persistence.Database.Postgres/DependencyInjection.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Npgsql; namespace Persistence.Database.Model; @@ -10,8 +11,12 @@ public static class DependencyInjection { string connectionStringName = "DefaultConnection"; - services.AddDbContext(options => - options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); + services.AddDbContext(options => + { + var dataSourceBuilder = new NpgsqlDataSourceBuilder(configuration.GetConnectionString(connectionStringName)); + dataSourceBuilder.EnableDynamicJson(); + options.UseNpgsql(dataSourceBuilder.Build()); + }); services.AddScoped(provider => provider.GetRequiredService()); diff --git a/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs b/Persistence.Database.Postgres/Migrations/20241126071115_Add_ChangeLog.Designer.cs similarity index 82% rename from Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs rename to Persistence.Database.Postgres/Migrations/20241126071115_Add_ChangeLog.Designer.cs index df89efd..c17da2b 100644 --- a/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.Designer.cs +++ b/Persistence.Database.Postgres/Migrations/20241126071115_Add_ChangeLog.Designer.cs @@ -1,5 +1,6 @@ // using System; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -12,8 +13,8 @@ using Persistence.Database.Model; namespace Persistence.Database.Postgres.Migrations { [DbContext(typeof(PersistenceDbContext))] - [Migration("20241122124437_AddChangeLog")] - partial class AddChangeLog + [Migration("20241126071115_Add_ChangeLog")] + partial class Add_ChangeLog { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -38,23 +39,39 @@ namespace Persistence.Database.Postgres.Migrations .HasColumnType("timestamp with time zone") .HasColumnName("Creation"); - b.Property("IdAuthor") - .HasColumnType("integer") + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("DepthEnd"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("DepthStart"); + + b.Property("IdAuthor") + .HasColumnType("uuid") .HasColumnName("IdAuthor"); - b.Property("IdEditor") - .HasColumnType("integer") + b.Property("IdDiscriminator") + .HasColumnType("uuid") + .HasColumnName("IdDiscriminator"); + + b.Property("IdEditor") + .HasColumnType("uuid") .HasColumnName("IdEditor"); - b.Property("IdNext") - .HasColumnType("integer") + b.Property("IdNext") + .HasColumnType("uuid") .HasColumnName("IdNext"); + b.Property("IdSection") + .HasColumnType("uuid") + .HasColumnName("IdSection"); + b.Property("Obsolete") .HasColumnType("timestamp with time zone") .HasColumnName("Obsolete"); - b.Property("Value") + b.Property>("Value") .IsRequired() .HasColumnType("jsonb") .HasColumnName("Value"); diff --git a/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs b/Persistence.Database.Postgres/Migrations/20241126071115_Add_ChangeLog.cs similarity index 58% rename from Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs rename to Persistence.Database.Postgres/Migrations/20241126071115_Add_ChangeLog.cs index 70aad1d..0802b00 100644 --- a/Persistence.Database.Postgres/Migrations/20241122124437_AddChangeLog.cs +++ b/Persistence.Database.Postgres/Migrations/20241126071115_Add_ChangeLog.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -6,7 +7,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace Persistence.Database.Postgres.Migrations { /// - public partial class AddChangeLog : Migration + public partial class Add_ChangeLog : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -16,12 +17,16 @@ namespace Persistence.Database.Postgres.Migrations columns: table => new { Id = table.Column(type: "uuid", nullable: false), - IdAuthor = table.Column(type: "integer", nullable: false), - IdEditor = table.Column(type: "integer", nullable: true), + IdDiscriminator = table.Column(type: "uuid", nullable: false), + IdAuthor = table.Column(type: "uuid", nullable: false), + IdEditor = table.Column(type: "uuid", nullable: true), Creation = table.Column(type: "timestamp with time zone", nullable: false), Obsolete = table.Column(type: "timestamp with time zone", nullable: true), - IdNext = table.Column(type: "integer", nullable: true), - Value = table.Column(type: "jsonb", nullable: false) + IdNext = table.Column(type: "uuid", nullable: true), + DepthStart = table.Column(type: "double precision", nullable: false), + DepthEnd = table.Column(type: "double precision", nullable: false), + IdSection = table.Column(type: "uuid", nullable: false), + Value = table.Column>(type: "jsonb", nullable: false) }, constraints: table => { diff --git a/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs b/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs index 99dab9a..230d3ab 100644 --- a/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs +++ b/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs @@ -1,5 +1,6 @@ // using System; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -35,23 +36,39 @@ namespace Persistence.Database.Postgres.Migrations .HasColumnType("timestamp with time zone") .HasColumnName("Creation"); - b.Property("IdAuthor") - .HasColumnType("integer") + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("DepthEnd"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("DepthStart"); + + b.Property("IdAuthor") + .HasColumnType("uuid") .HasColumnName("IdAuthor"); - b.Property("IdEditor") - .HasColumnType("integer") + b.Property("IdDiscriminator") + .HasColumnType("uuid") + .HasColumnName("IdDiscriminator"); + + b.Property("IdEditor") + .HasColumnType("uuid") .HasColumnName("IdEditor"); - b.Property("IdNext") - .HasColumnType("integer") + b.Property("IdNext") + .HasColumnType("uuid") .HasColumnName("IdNext"); + b.Property("IdSection") + .HasColumnType("uuid") + .HasColumnName("IdSection"); + b.Property("Obsolete") .HasColumnType("timestamp with time zone") .HasColumnName("Obsolete"); - b.Property("Value") + b.Property>("Value") .IsRequired() .HasColumnType("jsonb") .HasColumnName("Value"); diff --git a/Persistence.Database.Postgres/Readme.md b/Persistence.Database.Postgres/Readme.md index 756a8f5..7172774 100644 --- a/Persistence.Database.Postgres/Readme.md +++ b/Persistence.Database.Postgres/Readme.md @@ -2,4 +2,10 @@ ``` dotnet ef migrations add --project Persistence.Database.Postgres -``` \ No newline at end of file +``` + +## Откатить миграцию +``` +dotnet ef migrations remove --project Persistence.Database.Postgres +``` +Удаляется последняя созданная миграция. \ No newline at end of file diff --git a/Persistence.Database/Entity/ChangeLog.cs b/Persistence.Database/Entity/ChangeLog.cs index 59802ae..7100fc1 100644 --- a/Persistence.Database/Entity/ChangeLog.cs +++ b/Persistence.Database/Entity/ChangeLog.cs @@ -51,6 +51,24 @@ public class ChangeLog : IChangeLog [Column("IdNext")] public Guid? IdNext { get; set; } + /// + /// Глубина забоя на дату начала интервала + /// + [Column("DepthStart")] + public double DepthStart { get; set; } + + /// + /// Глубина забоя на дату окончания интервала + /// + [Column("DepthEnd")] + public double DepthEnd { get; set; } + + /// + /// Ключ секции + /// + [Column("IdSection")] + public Guid IdSection { get; set; } + /// /// Значение /// diff --git a/Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs b/Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs deleted file mode 100644 index abbe58f..0000000 --- a/Persistence.Database/Entity/ChangeLogWithWellDepthAndSectionId.cs +++ /dev/null @@ -1,29 +0,0 @@ - -using System.ComponentModel.DataAnnotations.Schema; -using System.ComponentModel.DataAnnotations; - -namespace Persistence.Database.Model; - -/// -/// Часть записи, описывающая изменение данных, содержащие начальную и конечную глубину, а также секцию -/// -public class ChangeLogWithWellDepthAndSectionId : ChangeLog -{ - /// - /// Глубина забоя на дату начала интервала - /// - [Column("DepthStart")] - public double? DepthStart { get; set; } - - /// - /// Глубина забоя на дату окончания интервала - /// - [Column("DepthEnd")] - public double? DepthEnd { get; set; } - - /// - /// Ключ секции - /// - [Column("IdSection")] - public Guid IdSection { get; set; } -} diff --git a/Persistence.Database/Entity/IChangeLog.cs b/Persistence.Database/Entity/IChangeLog.cs index 449c691..04e08a4 100644 --- a/Persistence.Database/Entity/IChangeLog.cs +++ b/Persistence.Database/Entity/IChangeLog.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Persistence.Database.Model; /// -/// Часть записи описывающая изменение +/// Часть записи, описывающая изменение /// public interface IChangeLog { diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index f0d8141..f659697 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -24,7 +24,7 @@ public class ChangeLogRepository : IChangeLogRepository throw new NotImplementedException(); } - public Task>>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) + public Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) { throw new NotImplementedException(); } @@ -44,7 +44,7 @@ public class ChangeLogRepository : IChangeLogRepository throw new NotImplementedException(); } - public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable> dtos, CancellationToken token) + public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var entities = new List(); foreach (var dto in dtos) @@ -54,8 +54,11 @@ public class ChangeLogRepository : IChangeLogRepository IdAuthor = idUser, IdDiscriminator = idDiscriminator, IdEditor = idUser, - Value = dto, - Creation = DateTimeOffset.UtcNow + Value = dto.Value, + Creation = DateTimeOffset.UtcNow, + IdSection = dto.IdSection, + DepthStart = dto.DepthStart, + DepthEnd = dto.DepthEnd, }; entity.Id = idUser; diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index 6cb0896..4752fb7 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -21,7 +21,7 @@ public interface IChangeLogApi /// /// /// - Task>>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token); + Task>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token); /// /// Добавить одну запись @@ -29,7 +29,7 @@ public interface IChangeLogApi /// /// /// - Task> Add(Guid idDiscriminator, IDictionary dto, CancellationToken token); + Task> Add(Guid idDiscriminator, ChangeLogDto dto, CancellationToken token); /// /// Добавить несколько записей diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index 8f716f4..14cbccc 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -1,20 +1,14 @@ - namespace Persistence.Models; /// /// Часть записи описывающая изменение /// -public class ChangeLogDto : IChangeLogDto - where T: IDictionary +public class ChangeLogDto { public ChangeLogDto() { - + } - /// - /// Запись - /// - public required T Item { get; set; } /// /// @@ -46,8 +40,23 @@ public class ChangeLogDto : IChangeLogDto /// public Guid? IdNext { get; set; } + /// + /// Глубина забоя на дату начала интервала + /// + public double DepthStart { get; set; } + + /// + /// Глубина забоя на дату окончания интервала + /// + public double DepthEnd { get; set; } + + /// + /// Ключ секции + /// + public Guid IdSection { get; set; } + /// /// Объект записи /// - public required object Value { get; set; } + public required IDictionary Value { get; set; } } diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index 06fbeb2..38b5dd2 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -16,7 +16,7 @@ public interface IChangeLogRepository //: ISyncRepository /// /// /// - Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable> dtos, CancellationToken token); + Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Редактирование записей @@ -76,7 +76,7 @@ public interface IChangeLogRepository //: ISyncRepository /// /// /// - Task>>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token); + Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token); /// /// Получение текущих сейчас записей по параметрам -- 2.45.2 From a3d90e05f73effed71b206bdf870c98fcd5e4953 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Wed, 27 Nov 2024 17:59:37 +0500 Subject: [PATCH 06/23] =?UTF-8?q?ChangeLog=20=D1=80=D0=B5=D0=BF=D0=BE?= =?UTF-8?q?=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 81 ++++++--- Persistence.API/DependencyInjection.cs | 4 +- Persistence.API/Persistence.API.csproj | 3 +- Persistence.API/Startup.cs | 4 + .../Repositories/ChangeLogRepository.cs | 164 ++++++++++++++---- Persistence/API/IChangeLogApi.cs | 38 ++-- Persistence/Models/ChangeLogDto.cs | 22 +-- .../Models/DataWithWellDepthAndSectionDto.cs | 43 +++++ .../Repositories/IChangeLogRepository.cs | 29 ++-- 9 files changed, 290 insertions(+), 98 deletions(-) create mode 100644 Persistence/Models/DataWithWellDepthAndSectionDto.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index dd92e04..9ce80b0 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Persistence.Database.Model; using Persistence.Models; using Persistence.Repositories; @@ -20,8 +19,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpPost] public async Task> Add( - [FromRoute] Guid idDiscriminator, - ChangeLogDto dto, + Guid idDiscriminator, + [FromBody] DataWithWellDepthAndSectionDto dto, CancellationToken token) { var userId = User.GetUserId(); @@ -31,50 +30,88 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpPost("range")] - public Task> AddRange(IEnumerable> dtos, CancellationToken token) + public async Task> AddRange( + Guid idDiscriminator, + [FromBody] IEnumerable dtos, CancellationToken token) { - throw new NotImplementedException(); + var userId = User.GetUserId(); + var result = await repository.InsertRange(userId, idDiscriminator, dtos, token); + + return Ok(result); } [HttpDelete] - public Task> Delete(int id, CancellationToken token) + public async Task> Delete(Guid id, CancellationToken token) { - throw new NotImplementedException(); + var userId = User.GetUserId(); + var result = await repository.MarkAsDeleted(userId, [id], token); + + return Ok(result); } [HttpDelete("range")] - public Task> DeleteRange(IEnumerable ids, CancellationToken token) + public async Task> DeleteRange(IEnumerable ids, CancellationToken token) { - throw new NotImplementedException(); + var userId = User.GetUserId(); + var result = await repository.MarkAsDeleted(userId, ids, token); + + return Ok(result); } [HttpGet] - public Task>>> GetChangeLogCurrent(CancellationToken token) + public async Task>> GetCurrent( + Guid idDiscriminator, + CancellationToken token) { - throw new NotImplementedException(); + var date = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); + var result = await repository.GetByDate(idDiscriminator, date, token); + + return Ok(result); + } + + [HttpGet("moment")] + public async Task>> GetByDate( + Guid idDiscriminator, + DateTimeOffset moment, + CancellationToken token) + { + var result = await repository.GetByDate(idDiscriminator, moment, token); + + return Ok(result); } [HttpGet("history")] - public Task>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) + public async Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) { - throw new NotImplementedException(); + var result = await repository.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd, token); + + return Ok(result); } - //[HttpGet("history")] - //public Task>>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token) - //{ - // throw new NotImplementedException(); - //} [HttpPut] - public Task> Update(IDictionary dto, CancellationToken token) + public async Task> Update( + Guid idDiscriminator, + DataWithWellDepthAndSectionDto dto, + CancellationToken token) { - throw new NotImplementedException(); + var userId = User.GetUserId(); + var result = await repository.UpdateRange(userId, idDiscriminator, [dto], token); + + return Ok(result); } [HttpPut("range")] - public Task> UpdateRange(IEnumerable> dtos, CancellationToken token) + public async Task> UpdateRange( + Guid idDiscriminator, + IEnumerable dtos, + CancellationToken token) { - throw new NotImplementedException(); + var userId = User.GetUserId(); + var result = await repository.UpdateRange(userId, idDiscriminator, dtos, token); + + return Ok(result); } + + } diff --git a/Persistence.API/DependencyInjection.cs b/Persistence.API/DependencyInjection.cs index cdfca4c..81713e4 100644 --- a/Persistence.API/DependencyInjection.cs +++ b/Persistence.API/DependencyInjection.cs @@ -59,7 +59,7 @@ public static class DependencyInjection private static void AddKeyCloakAuthentication(this IServiceCollection services, IConfiguration configuration) { - services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.RequireHttpsMetadata = false; @@ -69,7 +69,7 @@ public static class DependencyInjection { ValidIssuer = configuration["Authentication:ValidIssuer"], }; - }); + }); } private static void AddDefaultAuthentication(this IServiceCollection services, IConfiguration configuration) diff --git a/Persistence.API/Persistence.API.csproj b/Persistence.API/Persistence.API.csproj index 2b8cb73..c14b509 100644 --- a/Persistence.API/Persistence.API.csproj +++ b/Persistence.API/Persistence.API.csproj @@ -8,7 +8,8 @@ - + + diff --git a/Persistence.API/Startup.cs b/Persistence.API/Startup.cs index e074845..57365fa 100644 --- a/Persistence.API/Startup.cs +++ b/Persistence.API/Startup.cs @@ -22,6 +22,7 @@ public class Startup services.AddSwagger(Configuration); services.AddInfrastructure(); services.AddPersistenceDbContext(Configuration); + services.AddAuthorization(); services.AddJWTAuthentication(Configuration); } @@ -38,6 +39,9 @@ public class Startup app.UseDeveloperExceptionPage(); } + + app.UseHttpsRedirection(); + app.UseAuthentication(); app.UseAuthorization(); diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index f659697..361a9df 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -14,24 +14,91 @@ public class ChangeLogRepository : IChangeLogRepository this.db = db; } - public Task Clear(int idUser, CancellationToken token) + public async Task Clear(Guid idUser, Guid idDiscriminator, CancellationToken token) { - throw new NotImplementedException(); + var updateTime = DateTimeOffset.UtcNow; + + var dbSet = db.Set(); + var query = dbSet + .Where(s => s.IdDiscriminator == idDiscriminator) + .Where(e => e.Obsolete == null); + + var entitiesToDelete = await query.ToArrayAsync(token); + + foreach (var entity in entitiesToDelete) + { + entity.Obsolete = updateTime; + entity.IdEditor = idUser; + } + + return await db.SaveChangesAsync(token); } - public Task ClearAndInsertRange(int idUser, IEnumerable> dtos, CancellationToken token) + public async Task ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { - throw new NotImplementedException(); + var result = 0; + using var transaction = await db.Database.BeginTransactionAsync(token); + try + { + result += await Clear(idUser, idDiscriminator, token); + result += await InsertRange(idUser, idDiscriminator, dtos, token); + + await transaction.CommitAsync(token); + return result; + } + catch + { + await transaction.RollbackAsync(token); + throw; + } } - public Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) + public async Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) { - throw new NotImplementedException(); + var dbSet = db.Set(); + var query = dbSet.Where(s => s.IdDiscriminator == idDiscriminator); + + var min = dateBegin; + var max = dateEnd; + + var createdQuery = query.Where(e => e.Creation >= min && e.Creation <= max); + var editedQuery = query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max); + + query = createdQuery.Union(editedQuery); + var entities = await query.ToListAsync(token); + + var dtos = entities.Select(e => new ChangeLogDto + { + Creation = e.Creation, + IdAuthor = e.IdAuthor, + IdEditor = e.IdEditor, + IdNext = e.IdNext, + Obsolete = e.Obsolete, + Value = new DataWithWellDepthAndSectionDto() + { + Value = e.Value, + IdSection = e.IdSection, + Id = e.Id, + DepthEnd = e.DepthEnd, + DepthStart = e.DepthStart + } + }); + + return dtos; } - public Task>> GetCurrent(DateTimeOffset moment, CancellationToken token) + public async Task> GetByDate(Guid idDiscriminator, DateTimeOffset momentUtc, CancellationToken token) { - throw new NotImplementedException(); + var dbSet = db.Set(); + var dbQuery = dbSet + .Where(s => s.IdDiscriminator == idDiscriminator) + .Where(e => e.Creation <= momentUtc) + .Where(e => e.Obsolete == null || e.Obsolete >= momentUtc); + + var entities = await dbQuery.ToArrayAsync(token); + var dtos = entities.Select(e => e.Adapt()); + + return dtos; } public Task> GetDatesChange(CancellationToken token) @@ -44,36 +111,54 @@ public class ChangeLogRepository : IChangeLogRepository throw new NotImplementedException(); } - public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { - var entities = new List(); foreach (var dto in dtos) { - var entity = new ChangeLog() - { - IdAuthor = idUser, - IdDiscriminator = idDiscriminator, - IdEditor = idUser, - Value = dto.Value, - Creation = DateTimeOffset.UtcNow, - IdSection = dto.IdSection, - DepthStart = dto.DepthStart, - DepthEnd = dto.DepthEnd, - }; - entity.Id = idUser; - - entities.Add(entity); + var entity = CreateEntityFromDto(idUser, idDiscriminator, dto); + db.Set().Add(entity); } - db.Set().AddRange(entities); var result = db.SaveChangesAsync(token); return result; } - public Task MarkAsDeleted(int idUser, IEnumerable ids, CancellationToken token) + private ChangeLog CreateEntityFromDto(Guid idUser, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) { - throw new NotImplementedException(); + var entity = new ChangeLog() + { + Id = default, + Creation = DateTimeOffset.UtcNow, + IdAuthor = idUser, + IdDiscriminator = idDiscriminator, + IdEditor = idUser, + + Value = dto.Value, + IdSection = dto.IdSection, + DepthStart = dto.DepthStart, + DepthEnd = dto.DepthEnd, + }; + + return entity; + } + + public async Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token) + { + var result = 0; + var dbSet = db.Set(); + + var updatedEntity = dbSet + .Where(s => ids.Contains(s.Id)) + .FirstOrDefault(); + if (updatedEntity != null) + { + updatedEntity.Obsolete = DateTimeOffset.UtcNow; + + result = await db.SaveChangesAsync(token); + } + + return result; } public Task UpdateOrInsertRange(int idUser, IEnumerable> dtos, CancellationToken token) @@ -81,8 +166,29 @@ public class ChangeLogRepository : IChangeLogRepository throw new NotImplementedException(); } - public Task UpdateRange(int idUser, IEnumerable> dtos, CancellationToken token) + public async Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { - throw new NotImplementedException(); + var dbSet = db.Set(); + + var updatedIds = dtos.Select(d => d.Id); + var updatedEntities = dbSet + .Where(s => updatedIds.Contains(s.Id)) + .ToDictionary(s => s.Id); + //todo + foreach (var dto in dtos) + { + var newEntity = CreateEntityFromDto(idUser, idDiscriminator, dto); + dbSet.Add(newEntity); + + var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id)!; + updatedEntity.IdNext = newEntity.Id; + updatedEntity.Obsolete = DateTimeOffset.UtcNow; + updatedEntity.IdEditor = idUser; + + } + + var result = await db.SaveChangesAsync(token); + + return result; } } diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index 4752fb7..5419e2d 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -9,51 +9,67 @@ namespace Persistence.API; public interface IChangeLogApi { /// - /// Получение исторических данных на текущую дату + /// Получение данных на текущую дату /// + /// /// /// - Task>>> GetChangeLogCurrent(CancellationToken token); + Task>> GetCurrent(Guid idDiscriminator, CancellationToken token); /// - /// Получение исторических данных на определенную дату + /// Получение данных на определенную дату /// - /// + /// + /// /// /// - Task>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token); + Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, CancellationToken token); + + /// + /// Получение исторических данных за определенный период времени + /// + /// + /// + /// + /// + /// + Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); /// /// Добавить одну запись /// + /// /// /// /// - Task> Add(Guid idDiscriminator, ChangeLogDto dto, CancellationToken token); + Task> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); /// /// Добавить несколько записей /// + /// /// /// /// - Task> AddRange(IEnumerable> dtos, CancellationToken token); + Task> AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Обновить одну запись /// + /// /// /// /// - Task> Update(IDictionary dto, CancellationToken token); + Task> Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); /// /// Обновить несколько записей /// + /// /// /// /// - Task> UpdateRange(IEnumerable> dtos, CancellationToken token); + Task> UpdateRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Удалить одну запись @@ -61,7 +77,7 @@ public interface IChangeLogApi /// /// /// - Task> Delete(int id, CancellationToken token); + Task> Delete(Guid id, CancellationToken token); /// /// Удалить несколько записей @@ -69,5 +85,5 @@ public interface IChangeLogApi /// /// /// - Task> DeleteRange(IEnumerable ids, CancellationToken token); + Task> DeleteRange(IEnumerable ids, CancellationToken token); } diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index 14cbccc..aa8963f 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -10,11 +10,6 @@ public class ChangeLogDto } - /// - /// - /// - public Guid Id { get; set; } - /// /// Создатель записи /// @@ -40,23 +35,8 @@ public class ChangeLogDto /// public Guid? IdNext { get; set; } - /// - /// Глубина забоя на дату начала интервала - /// - public double DepthStart { get; set; } - - /// - /// Глубина забоя на дату окончания интервала - /// - public double DepthEnd { get; set; } - - /// - /// Ключ секции - /// - public Guid IdSection { get; set; } - /// /// Объект записи /// - public required IDictionary Value { get; set; } + public DataWithWellDepthAndSectionDto Value { get; set; } } diff --git a/Persistence/Models/DataWithWellDepthAndSectionDto.cs b/Persistence/Models/DataWithWellDepthAndSectionDto.cs new file mode 100644 index 0000000..b3747c2 --- /dev/null +++ b/Persistence/Models/DataWithWellDepthAndSectionDto.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Persistence.Models; + +/// +/// Dto для хранения записей, содержащих начальную и конечную глубину забоя, а также секцию +/// +public class DataWithWellDepthAndSectionDto +{ + public DataWithWellDepthAndSectionDto() + { + + } + + /// + /// Ключ записи + /// + public Guid Id { get; set; } + + /// + /// Глубина забоя на дату начала интервала + /// + public double DepthStart { get; set; } + + /// + /// Глубина забоя на дату окончания интервала + /// + public double DepthEnd { get; set; } + + /// + /// Ключ секции + /// + public Guid IdSection { get; set; } + + /// + /// Объект записи + /// + public required IDictionary Value { get; set; } = default!; +} diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index 38b5dd2..ab4f4a9 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -16,16 +16,17 @@ public interface IChangeLogRepository //: ISyncRepository /// /// /// - Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Редактирование записей /// /// пользователь, который редактирует + /// /// /// /// - Task UpdateRange(int idUser, IEnumerable> dtos, CancellationToken token); + Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Добавляет Dto у которых id == 0, изменяет dto у которых id != 0 @@ -39,19 +40,20 @@ public interface IChangeLogRepository //: ISyncRepository /// /// Помечает записи как удаленные /// - /// пользователь, который чистит + /// /// /// - Task Clear(int idUser, CancellationToken token); + Task Clear(Guid idUser, Guid idDiscriminator, CancellationToken token); /// /// Очистить и добавить новые /// /// + /// /// /// /// - Task ClearAndInsertRange(int idUser, IEnumerable> dtos, CancellationToken token); + Task ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Пометить записи как удаленные @@ -60,7 +62,7 @@ public interface IChangeLogRepository //: ISyncRepository /// /// /// - Task MarkAsDeleted(int idUser, IEnumerable ids, CancellationToken token); + Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token); /// /// Получение дат изменений записей @@ -71,18 +73,21 @@ public interface IChangeLogRepository //: ISyncRepository Task> GetDatesChange(CancellationToken token); /// - /// Получение измененных записей за определенную дату + /// Получение измененных записей за период времени /// - /// + /// + /// + /// /// /// - Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token); + Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); /// - /// Получение текущих сейчас записей по параметрам + /// Получение актуальных записей на определенный момент времени /// - /// + /// + /// текущий момент времени /// /// - Task>> GetCurrent(DateTimeOffset moment, CancellationToken token); + Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, CancellationToken token); } -- 2.45.2 From 198a65b1d240aa93b8ff46514a174fd611dbcfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Thu, 28 Nov 2024 16:29:00 +0500 Subject: [PATCH 07/23] =?UTF-8?q?ChangeLogRepository=20(=D0=BE=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=87=D0=B0=D0=BD=D0=B8=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 76 +++-- Persistence.Repository/DependencyInjection.cs | 12 + .../Repositories/ChangeLogRepository.cs | 273 +++++++++++------- Persistence/API/IChangeLogApi.cs | 28 +- Persistence/API/ITableDataApi.cs | 8 +- Persistence/EFExtensions.cs | 114 ++++++++ .../{RequestDto.cs => Requests/Request.cs} | 12 +- .../Models/Requests/SectionPartRequest.cs | 22 ++ .../Repositories/IChangeLogRepository.cs | 56 ++-- .../Repositories/ITableDataRepository.cs | 4 +- 10 files changed, 427 insertions(+), 178 deletions(-) create mode 100644 Persistence/EFExtensions.cs rename Persistence/Models/{RequestDto.cs => Requests/Request.cs} (58%) create mode 100644 Persistence/Models/Requests/SectionPartRequest.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 9ce80b0..8bfa32f 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Persistence.Models; +using Persistence.Models.Requests; using Persistence.Repositories; namespace Persistence.API.Controllers; @@ -58,37 +59,17 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } - [HttpGet] - public async Task>> GetCurrent( - Guid idDiscriminator, + [HttpPost("replace")] + public async Task ClearAndInsertRange( + Guid idDiscriminator, + IEnumerable dtos, CancellationToken token) { - var date = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); - var result = await repository.GetByDate(idDiscriminator, date, token); - + var userId = User.GetUserId(); + var result = await repository.ClearAndInsertRange(userId, idDiscriminator, dtos, token); return Ok(result); } - [HttpGet("moment")] - public async Task>> GetByDate( - Guid idDiscriminator, - DateTimeOffset moment, - CancellationToken token) - { - var result = await repository.GetByDate(idDiscriminator, moment, token); - - return Ok(result); - } - - [HttpGet("history")] - public async Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) - { - var result = await repository.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd, token); - - return Ok(result); - } - - [HttpPut] public async Task> Update( Guid idDiscriminator, @@ -113,5 +94,48 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } + [HttpGet] + public async Task>> GetCurrent( + Guid idDiscriminator, + [FromQuery]SectionPartRequest request, + CancellationToken token) + { + var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); + var result = await repository.GetByDate(idDiscriminator, moment, request, token); + + return Ok(result); + } + + [HttpGet("moment")] + public async Task>> GetByDate( + Guid idDiscriminator, + DateTimeOffset moment, + SectionPartRequest request, + CancellationToken token) + { + var result = await repository.GetByDate(idDiscriminator, moment, request, token); + + return Ok(result); + } + + [HttpGet("history")] + public async Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + { + var result = await repository.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd, token); + + return Ok(result); + } + + [HttpGet("datesChange")] + public async Task>> GetDatesChange(Guid idDiscriminator, CancellationToken token) + { + var result = await repository.GetDatesChange(idDiscriminator, token); + + return Ok(result); + } + + + + } diff --git a/Persistence.Repository/DependencyInjection.cs b/Persistence.Repository/DependencyInjection.cs index 013f97f..7f268a3 100644 --- a/Persistence.Repository/DependencyInjection.cs +++ b/Persistence.Repository/DependencyInjection.cs @@ -1,3 +1,4 @@ +using Mapster; using Microsoft.Extensions.DependencyInjection; using Persistence.Database.Model; using Persistence.Models; @@ -10,6 +11,17 @@ public static class DependencyInjection { public static void MapsterSetup() { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Map(dest => dest.Value, src => new DataWithWellDepthAndSectionDto() + { + DepthEnd = src.DepthEnd, + DepthStart = src.DepthStart, + IdSection = src.IdSection, + Value = src.Value, + Id = src.Id + }); + } public static IServiceCollection AddInfrastructure(this IServiceCollection services) diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 361a9df..5bfb870 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore; using Persistence.Database.Model; using Persistence.Models; +using Persistence.Models.Requests; using Persistence.Repositories; namespace Persistence.Repository.Repositories; @@ -14,18 +15,46 @@ public class ChangeLogRepository : IChangeLogRepository this.db = db; } - public async Task Clear(Guid idUser, Guid idDiscriminator, CancellationToken token) + public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + { + foreach (var dto in dtos) + { + var entity = CreateEntityFromDto(idUser, idDiscriminator, dto); + db.Set().Add(entity); + } + + var result = db.SaveChangesAsync(token); + + return result; + } + + public async Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token) + { + var query = db.Set().Where(s => ids.Contains(s.Id)); + var entities = await query.ToArrayAsync(token); + + var result = await Clear(idUser, entities, token); + + return result; + } + + public async Task MarkAsDeleted(Guid idUser, Guid idDiscriminator, CancellationToken token) + { + var query = db.Set() + .Where(s => s.IdDiscriminator == idDiscriminator) + .Where(e => e.Obsolete == null); + var entities = await query.ToArrayAsync(token); + + var result = await Clear(idUser, entities, token); + + return result; + } + + private async Task Clear(Guid idUser, IEnumerable entities, CancellationToken token) { var updateTime = DateTimeOffset.UtcNow; - var dbSet = db.Set(); - var query = dbSet - .Where(s => s.IdDiscriminator == idDiscriminator) - .Where(e => e.Obsolete == null); - - var entitiesToDelete = await query.ToArrayAsync(token); - - foreach (var entity in entitiesToDelete) + foreach (var entity in entities) { entity.Obsolete = updateTime; entity.IdEditor = idUser; @@ -40,7 +69,7 @@ public class ChangeLogRepository : IChangeLogRepository using var transaction = await db.Database.BeginTransactionAsync(token); try { - result += await Clear(idUser, idDiscriminator, token); + result += await MarkAsDeleted(idUser, idDiscriminator, token); result += await InsertRange(idUser, idDiscriminator, dtos, token); await transaction.CommitAsync(token); @@ -53,57 +82,154 @@ public class ChangeLogRepository : IChangeLogRepository } } - public async Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + public async Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var dbSet = db.Set(); - var query = dbSet.Where(s => s.IdDiscriminator == idDiscriminator); - var min = dateBegin; - var max = dateEnd; + var updatedIds = dtos.Select(d => d.Id); + var updatedEntities = dbSet + .Where(s => updatedIds.Contains(s.Id)) + .ToDictionary(s => s.Id); + + var result = 0; + using var transaction = await db.Database.BeginTransactionAsync(token); + try + { + foreach (var dto in dtos) + { + var newEntity = CreateEntityFromDto(idUser, idDiscriminator, dto); + dbSet.Add(newEntity); + + var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id)!; + updatedEntity.IdNext = newEntity.Id; + updatedEntity.Obsolete = DateTimeOffset.UtcNow; + updatedEntity.IdEditor = idUser; + } + + await db.SaveChangesAsync(token); + await transaction.CommitAsync(token); + + return result; + } + catch + { + await transaction.RollbackAsync(token); + throw; + } + } + + public async Task> GetByDate( + Guid idDiscriminator, + DateTimeOffset momentUtc, + SectionPartRequest request, + CancellationToken token) + { + var query = BuildQuery(idDiscriminator, momentUtc, request); + var result = await BuildPaginationContainer(query, request, token); + + return result; + } + + private IQueryable BuildQuery(Guid idDiscriminator, DateTimeOffset momentUtc, SectionPartRequest request) + { + var query = db.Set() + .Where(e => e.IdDiscriminator == idDiscriminator) + .Where(e => e.Creation <= momentUtc) + .Where(e => e.Obsolete == null || e.Obsolete >= momentUtc); + + if (request.IdSection.HasValue) + { + query = query.Where(e => e.IdSection == request.IdSection); + } + if (request.DepthStart.HasValue) + { + query = query.Where(e => e.DepthStart >= request.DepthStart); + } + if (request.DepthEnd.HasValue) + { + query = query.Where(e => e.DepthEnd <= request.DepthEnd); + } + + return query; + } + + public async Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + { + var query = db.Set().Where(s => s.IdDiscriminator == idDiscriminator); + + var min = new DateTimeOffset(dateBegin.Year, dateBegin.Month, dateBegin.Day, 0, 0, 0, TimeSpan.Zero); + var max = new DateTimeOffset(dateEnd.Year, dateEnd.Month, dateEnd.Day, 0, 0, 0, TimeSpan.Zero); var createdQuery = query.Where(e => e.Creation >= min && e.Creation <= max); var editedQuery = query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max); query = createdQuery.Union(editedQuery); - var entities = await query.ToListAsync(token); + var entities = await query.ToArrayAsync(token); - var dtos = entities.Select(e => new ChangeLogDto + var dtos = entities.Select(e => e.Adapt()); + + return dtos; + } + + + + private async Task> BuildPaginationContainer(IQueryable query, SectionPartRequest request, CancellationToken token) + { + var result = new PaginationContainer { - Creation = e.Creation, - IdAuthor = e.IdAuthor, - IdEditor = e.IdEditor, - IdNext = e.IdNext, - Obsolete = e.Obsolete, - Value = new DataWithWellDepthAndSectionDto() - { - Value = e.Value, - IdSection = e.IdSection, - Id = e.Id, - DepthEnd = e.DepthEnd, - DepthStart = e.DepthStart - } - }); + Skip = request.Skip ?? 0, + Take = request.Take ?? 32, + Items = Enumerable.Empty(), + Count = await query.CountAsync(token) + }; - return dtos; - } + if (!String.IsNullOrEmpty(request.SortSettings)) + { + query = query.SortBy(request.SortSettings); + } + else + { + query = query + .OrderBy(e => e.IdSection) + .ThenBy(e => e.DepthStart) + .ThenBy(e => e.DepthEnd); + } - public async Task> GetByDate(Guid idDiscriminator, DateTimeOffset momentUtc, CancellationToken token) - { - var dbSet = db.Set(); - var dbQuery = dbSet - .Where(s => s.IdDiscriminator == idDiscriminator) - .Where(e => e.Creation <= momentUtc) - .Where(e => e.Obsolete == null || e.Obsolete >= momentUtc); + var entities = await query + .Skip(result.Skip) + .Take(result.Take) + .ToArrayAsync(token); - var entities = await dbQuery.ToArrayAsync(token); var dtos = entities.Select(e => e.Adapt()); + result.Items = dtos; - return dtos; + return result; } - public Task> GetDatesChange(CancellationToken token) + public async Task> GetDatesChange(Guid idDiscriminator, CancellationToken token) { - throw new NotImplementedException(); + var query = db.Set().Where(e => e.IdDiscriminator == idDiscriminator); + + var datesCreateQuery = query + .Select(e => e.Creation) + .Distinct(); + + var datesCreate = await datesCreateQuery.ToArrayAsync(token); + + var datesUpdateQuery = query + .Where(e => e.Obsolete != null) + .Select(e => e.Obsolete!.Value) + .Distinct(); + + var datesUpdate = await datesUpdateQuery.ToArrayAsync(token); + + var dates = Enumerable.Concat(datesCreate, datesUpdate); + var datesOnly = dates + .Select(d => new DateOnly(d.Year, d.Month, d.Day)) + .Distinct() + .OrderBy(d => d); + + return datesOnly; } public Task>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token) @@ -111,19 +237,6 @@ public class ChangeLogRepository : IChangeLogRepository throw new NotImplementedException(); } - public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) - { - foreach (var dto in dtos) - { - var entity = CreateEntityFromDto(idUser, idDiscriminator, dto); - db.Set().Add(entity); - } - - var result = db.SaveChangesAsync(token); - - return result; - } - private ChangeLog CreateEntityFromDto(Guid idUser, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) { var entity = new ChangeLog() @@ -143,52 +256,4 @@ public class ChangeLogRepository : IChangeLogRepository return entity; } - public async Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token) - { - var result = 0; - var dbSet = db.Set(); - - var updatedEntity = dbSet - .Where(s => ids.Contains(s.Id)) - .FirstOrDefault(); - if (updatedEntity != null) - { - updatedEntity.Obsolete = DateTimeOffset.UtcNow; - - result = await db.SaveChangesAsync(token); - } - - return result; - } - - public Task UpdateOrInsertRange(int idUser, IEnumerable> dtos, CancellationToken token) - { - throw new NotImplementedException(); - } - - public async Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) - { - var dbSet = db.Set(); - - var updatedIds = dtos.Select(d => d.Id); - var updatedEntities = dbSet - .Where(s => updatedIds.Contains(s.Id)) - .ToDictionary(s => s.Id); - //todo - foreach (var dto in dtos) - { - var newEntity = CreateEntityFromDto(idUser, idDiscriminator, dto); - dbSet.Add(newEntity); - - var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id)!; - updatedEntity.IdNext = newEntity.Id; - updatedEntity.Obsolete = DateTimeOffset.UtcNow; - updatedEntity.IdEditor = idUser; - - } - - var result = await db.SaveChangesAsync(token); - - return result; - } } diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index 5419e2d..a0f75a0 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Persistence.Models; +using Persistence.Models.Requests; namespace Persistence.API; @@ -9,21 +10,32 @@ namespace Persistence.API; public interface IChangeLogApi { /// - /// Получение данных на текущую дату + /// Импорт с заменой: удаление старых строк и добавление новых /// /// + /// /// /// - Task>> GetCurrent(Guid idDiscriminator, CancellationToken token); + Task ClearAndInsertRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// - /// Получение данных на определенную дату + /// Получение данных на текущую дату (с пагинацией) + /// + /// + /// параметры запроса + /// + /// + Task>> GetCurrent(Guid idDiscriminator, SectionPartRequest request, CancellationToken token); + + /// + /// Получение данных на определенную дату (с пагинацией) /// /// /// + /// параметры запроса /// /// - Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, CancellationToken token); + Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); /// /// Получение исторических данных за определенный период времени @@ -86,4 +98,12 @@ public interface IChangeLogApi /// /// Task> DeleteRange(IEnumerable ids, CancellationToken token); + + /// + /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) + /// + /// + /// + /// + Task>> GetDatesChange(Guid idDiscriminator, CancellationToken token); } diff --git a/Persistence/API/ITableDataApi.cs b/Persistence/API/ITableDataApi.cs index a310799..075559a 100644 --- a/Persistence/API/ITableDataApi.cs +++ b/Persistence/API/ITableDataApi.cs @@ -1,17 +1,13 @@ using Microsoft.AspNetCore.Mvc; using Persistence.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Persistence.Models.Requests; namespace Persistence.API; /// Интерфейс для API, предназначенного для работы с табличными данными public interface ITableDataApi where TDto : class, new() - where TRequest : RequestDto + where TRequest : Request { /// /// Получить страницу списка объектов diff --git a/Persistence/EFExtensions.cs b/Persistence/EFExtensions.cs new file mode 100644 index 0000000..00474cc --- /dev/null +++ b/Persistence/EFExtensions.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Persistence; +public static class EFExtensions +{ + struct TypeAcessor + { + public LambdaExpression KeySelector { get; set; } + public MethodInfo OrderBy { get; set; } + public MethodInfo OrderByDescending { get; set; } + public MethodInfo ThenBy { get; set; } + public MethodInfo ThenByDescending { get; set; } + } + private static readonly MethodInfo methodOrderBy = GetExtOrderMethod("OrderBy"); + + private static readonly MethodInfo methodOrderByDescending = GetExtOrderMethod("OrderByDescending"); + + private static readonly MethodInfo methodThenBy = GetExtOrderMethod("ThenBy"); + + private static readonly MethodInfo methodThenByDescending = GetExtOrderMethod("ThenByDescending"); + private static ConcurrentDictionary> TypePropSelectors { get; set; } = new(); + + private static MethodInfo GetExtOrderMethod(string methodName) + => typeof(System.Linq.Queryable) + .GetMethods() + .Where(m => m.Name == methodName && + m.IsGenericMethodDefinition && + m.GetParameters().Length == 2 && + m.GetParameters()[1].ParameterType.IsAssignableTo(typeof(LambdaExpression))) + .Single(); + private static Dictionary MakeTypeAcessors(Type type) + { + var propContainer = new Dictionary(); + var properties = type.GetProperties(); + foreach (var propertyInfo in properties) + { + var name = propertyInfo.Name.ToLower(); + ParameterExpression arg = Expression.Parameter(type, "x"); + MemberExpression property = Expression.Property(arg, propertyInfo.Name); + var selector = Expression.Lambda(property, new ParameterExpression[] { arg }); + var typeAccessor = new TypeAcessor + { + KeySelector = selector, + OrderBy = methodOrderBy.MakeGenericMethod(type, propertyInfo.PropertyType), + OrderByDescending = methodOrderByDescending.MakeGenericMethod(type, propertyInfo.PropertyType), + ThenBy = methodThenBy.MakeGenericMethod(type, propertyInfo.PropertyType), + ThenByDescending = methodThenByDescending.MakeGenericMethod(type, propertyInfo.PropertyType), + }; + + propContainer.Add(name, typeAccessor); + } + return propContainer; + } + + /// + /// Добавить в запрос сортировку по возрастанию или убыванию. + /// Этот метод сбросит ранее наложенные сортировки. + /// + /// + /// + /// + /// Свойство сортировки. + /// Состоит из названия свойства (в любом регистре) + /// и опционально указания направления сортировки "asc" или "desc" + /// + /// + /// var query = query("Date desc"); + /// + /// Запрос с примененной сортировкой + public static IOrderedQueryable SortBy( + this IQueryable query, + string propertySort) + { + var parts = propertySort.Split(" ", 2, StringSplitOptions.RemoveEmptyEntries); + var isDesc = parts.Length >= 2 && parts[1].ToLower().Trim() == "desc"; + var propertyName = parts[0]; + + var newQuery = query.SortBy(propertyName, isDesc); + return newQuery; + } + + /// + /// Добавить в запрос сортировку по возрастанию или убыванию + /// + /// + /// + /// Название свойства (в любом регистре) + /// Сортировать по убыванию + /// Запрос с примененной сортировкой + public static IOrderedQueryable SortBy( + this IQueryable query, + string propertyName, + bool isDesc) + { + var typePropSelector = TypePropSelectors.GetOrAdd(typeof(TSource), MakeTypeAcessors); + var propertyNamelower = propertyName.ToLower(); + var typeAccessor = typePropSelector[propertyNamelower]; + + var genericMethod = isDesc + ? typeAccessor.OrderByDescending + : typeAccessor.OrderBy; + + var newQuery = (IOrderedQueryable)genericMethod + .Invoke(genericMethod, new object[] { query, typeAccessor.KeySelector })!; + return newQuery; + } +} diff --git a/Persistence/Models/RequestDto.cs b/Persistence/Models/Requests/Request.cs similarity index 58% rename from Persistence/Models/RequestDto.cs rename to Persistence/Models/Requests/Request.cs index c61ac79..a53f5a9 100644 --- a/Persistence/Models/RequestDto.cs +++ b/Persistence/Models/Requests/Request.cs @@ -1,23 +1,25 @@ -namespace Persistence.Models; +namespace Persistence.Models.Requests; /// /// Контейнер для поддержки постраничного просмотра таблиц /// /// -public class RequestDto +public class Request { /// /// Кол-во записей пропущенных с начала таблицы в запросе от api /// - public int Skip { get; set; } + public int? Skip { get; set; } /// /// Кол-во записей в запросе от api /// - public int Take { get; set; } + public int? Take { get; set; } /// - /// Настройки сортировки + /// Сортировки: + /// Содержат список названий полей сортировки + /// Указать направление сортировки можно через пробел "asc" или "desc" /// public string SortSettings { get; set; } = string.Empty; } diff --git a/Persistence/Models/Requests/SectionPartRequest.cs b/Persistence/Models/Requests/SectionPartRequest.cs new file mode 100644 index 0000000..a05082d --- /dev/null +++ b/Persistence/Models/Requests/SectionPartRequest.cs @@ -0,0 +1,22 @@ +namespace Persistence.Models.Requests; + +/// +/// Запрос для фильтрации данных по секции и глубине +/// +public class SectionPartRequest : Request +{ + /// + /// Глубина забоя на дату начала интервала + /// + public double? DepthStart { get; set; } + + /// + /// Глубина забоя на дату окончания интервала + /// + public double? DepthEnd { get; set; } + + /// + /// Ключ секции + /// + public Guid? IdSection { get; set; } +} diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index ab4f4a9..b5cd53a 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -1,4 +1,5 @@ using Persistence.Models; +using Persistence.Models.Requests; namespace Persistence.Repositories; @@ -19,31 +20,22 @@ public interface IChangeLogRepository //: ISyncRepository Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// - /// Редактирование записей - /// - /// пользователь, который редактирует - /// - /// - /// - /// - Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); - - /// - /// Добавляет Dto у которых id == 0, изменяет dto у которых id != 0 - /// - /// пользователь, который редактирует или добавляет - /// - /// - /// - Task UpdateOrInsertRange(int idUser, IEnumerable> dtos, CancellationToken token); - - /// - /// Помечает записи как удаленные + /// Пометить записи как удаленные /// /// + /// ключи записей /// /// - Task Clear(Guid idUser, Guid idDiscriminator, CancellationToken token); + Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token); + + /// + /// Пометить записи как удаленные + /// + /// + /// дискриминатор таблицы + /// + /// + Task MarkAsDeleted(Guid idUser, Guid idDiscriminator, CancellationToken token); /// /// Очистить и добавить новые @@ -56,21 +48,24 @@ public interface IChangeLogRepository //: ISyncRepository Task ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// - /// Пометить записи как удаленные + /// Редактирование записей /// - /// - /// + /// пользователь, который редактирует + /// + /// /// /// - Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token); + Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// - /// Получение дат изменений записей + /// Получение актуальных записей на определенный момент времени (с пагинацией) /// - /// + /// + /// текущий момент времени + /// параметры запроса /// /// - Task> GetDatesChange(CancellationToken token); + Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); /// /// Получение измененных записей за период времени @@ -83,11 +78,10 @@ public interface IChangeLogRepository //: ISyncRepository Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); /// - /// Получение актуальных записей на определенный момент времени + /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) /// /// - /// текущий момент времени /// /// - Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, CancellationToken token); + Task> GetDatesChange(Guid idDiscriminator, CancellationToken token); } diff --git a/Persistence/Repositories/ITableDataRepository.cs b/Persistence/Repositories/ITableDataRepository.cs index 73d332d..574ff76 100644 --- a/Persistence/Repositories/ITableDataRepository.cs +++ b/Persistence/Repositories/ITableDataRepository.cs @@ -1,4 +1,4 @@ -using Persistence.Models; +using Persistence.Models.Requests; namespace Persistence.Repositories; @@ -7,7 +7,7 @@ namespace Persistence.Repositories; /// public interface ITableDataRepository where TDto : class, new() - where TRequest : RequestDto + where TRequest : Request { /// /// Получить страницу списка объектов -- 2.45.2 From 25afd507930361ff7e6c71fb6f80dc2420fefbe1 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 29 Nov 2024 10:03:52 +0500 Subject: [PATCH 08/23] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 32 +++++++++++++------ Persistence/API/IChangeLogApi.cs | 20 ++++++------ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 8bfa32f..08f059e 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Persistence.Models; using Persistence.Models.Requests; using Persistence.Repositories; +using System.Net; namespace Persistence.API.Controllers; @@ -19,7 +20,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpPost] - public async Task> Add( + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task Add( Guid idDiscriminator, [FromBody] DataWithWellDepthAndSectionDto dto, CancellationToken token) @@ -31,7 +33,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpPost("range")] - public async Task> AddRange( + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task AddRange( Guid idDiscriminator, [FromBody] IEnumerable dtos, CancellationToken token) { @@ -42,7 +45,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpDelete] - public async Task> Delete(Guid id, CancellationToken token) + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task Delete(Guid id, CancellationToken token) { var userId = User.GetUserId(); var result = await repository.MarkAsDeleted(userId, [id], token); @@ -51,7 +55,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpDelete("range")] - public async Task> DeleteRange(IEnumerable ids, CancellationToken token) + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task DeleteRange(IEnumerable ids, CancellationToken token) { var userId = User.GetUserId(); var result = await repository.MarkAsDeleted(userId, ids, token); @@ -60,6 +65,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpPost("replace")] + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task ClearAndInsertRange( Guid idDiscriminator, IEnumerable dtos, @@ -71,7 +77,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpPut] - public async Task> Update( + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task Update( Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token) @@ -83,7 +90,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpPut("range")] - public async Task> UpdateRange( + [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + public async Task UpdateRange( Guid idDiscriminator, IEnumerable dtos, CancellationToken token) @@ -95,7 +103,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpGet] - public async Task>> GetCurrent( + [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] + public async Task GetCurrent( Guid idDiscriminator, [FromQuery]SectionPartRequest request, CancellationToken token) @@ -107,7 +116,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpGet("moment")] - public async Task>> GetByDate( + [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] + public async Task GetByDate( Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, @@ -119,7 +129,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpGet("history")] - public async Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) { var result = await repository.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd, token); @@ -127,7 +138,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpGet("datesChange")] - public async Task>> GetDatesChange(Guid idDiscriminator, CancellationToken token) + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task GetDatesChange(Guid idDiscriminator, CancellationToken token) { var result = await repository.GetDatesChange(idDiscriminator, token); diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index a0f75a0..a46fc98 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -25,7 +25,7 @@ public interface IChangeLogApi /// параметры запроса /// /// - Task>> GetCurrent(Guid idDiscriminator, SectionPartRequest request, CancellationToken token); + Task GetCurrent(Guid idDiscriminator, SectionPartRequest request, CancellationToken token); /// /// Получение данных на определенную дату (с пагинацией) @@ -35,7 +35,7 @@ public interface IChangeLogApi /// параметры запроса /// /// - Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); + Task GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); /// /// Получение исторических данных за определенный период времени @@ -45,7 +45,7 @@ public interface IChangeLogApi /// /// /// - Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); + Task GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); /// /// Добавить одну запись @@ -54,7 +54,7 @@ public interface IChangeLogApi /// /// /// - Task> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); /// /// Добавить несколько записей @@ -63,7 +63,7 @@ public interface IChangeLogApi /// /// /// - Task> AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Обновить одну запись @@ -72,7 +72,7 @@ public interface IChangeLogApi /// /// /// - Task> Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); /// /// Обновить несколько записей @@ -81,7 +81,7 @@ public interface IChangeLogApi /// /// /// - Task> UpdateRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task UpdateRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Удалить одну запись @@ -89,7 +89,7 @@ public interface IChangeLogApi /// /// /// - Task> Delete(Guid id, CancellationToken token); + Task Delete(Guid id, CancellationToken token); /// /// Удалить несколько записей @@ -97,7 +97,7 @@ public interface IChangeLogApi /// /// /// - Task> DeleteRange(IEnumerable ids, CancellationToken token); + Task DeleteRange(IEnumerable ids, CancellationToken token); /// /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) @@ -105,5 +105,5 @@ public interface IChangeLogApi /// /// /// - Task>> GetDatesChange(Guid idDiscriminator, CancellationToken token); + Task GetDatesChange(Guid idDiscriminator, CancellationToken token); } -- 2.45.2 From c54e9cb35c25c8f72f049ad17929e437be7eefac Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 29 Nov 2024 11:52:47 +0500 Subject: [PATCH 09/23] =?UTF-8?q?ISyncWithDiscriminatorApi=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=81=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82=D0=B5=D0=B9?= =?UTF-8?q?,=20=D1=83=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D1=85=20?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8C=20=D0=B4=D0=B8=D1=81=D0=BA=D1=80=D0=B8?= =?UTF-8?q?=D0=BC=D0=B8=D0=BD=D0=B0=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 15 +++++++++- .../Repositories/ChangeLogRepository.cs | 26 +++++++++++++++++ Persistence/API/IChangeLogApi.cs | 2 +- Persistence/API/ISyncApi.cs | 2 +- Persistence/API/ISyncWithDiscriminatorApi.cs | 28 +++++++++++++++++++ .../Repositories/IChangeLogRepository.cs | 2 +- Persistence/Repositories/ISyncRepository.cs | 14 ++++++++-- .../ISyncWithDiscriminatorRepository.cs | 28 +++++++++++++++++++ .../Repositories/ITimeSeriesBaseRepository.cs | 7 ----- 9 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 Persistence/API/ISyncWithDiscriminatorApi.cs create mode 100644 Persistence/Repositories/ISyncWithDiscriminatorRepository.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 08f059e..f65cbb1 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -146,8 +146,21 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } + [HttpGet("part")] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task GetPart(Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default) + { + var result = await repository.GetGtDate(idDiscriminator, dateBegin, token); + return Ok(result); + } + [HttpGet("datesRange")] + [ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)] + public async Task GetDatesRangeAsync(Guid idDiscriminator, CancellationToken token) + { + var result = await repository.GetDatesRange(idDiscriminator, token); - + return Ok(result); + } } diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 5bfb870..98ff7d3 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -256,4 +256,30 @@ public class ChangeLogRepository : IChangeLogRepository return entity; } + public async Task> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token) + { + var date = dateBegin.ToUniversalTime(); + var query = this.db.Set() + .Where(e => e.IdDiscriminator == idDiscriminator) + .Where(e => e.Creation >= date || e.Obsolete >= date); + + var entities = await query.ToArrayAsync(token); + + var dtos = entities.Select(e => e.Adapt()); + + return dtos; + } + + public async Task GetDatesRange(Guid idDiscriminator, CancellationToken token) + { + var query = this.db.Set().Where(e => e.IdDiscriminator == idDiscriminator); + var minDate = await query.MinAsync(o => o.Creation, token); + var maxDate = await query.MaxAsync(o => o.Creation, token); + + return new DatesRangeDto + { + From = minDate, + To = maxDate + }; + } } diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index a46fc98..40ca8ae 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -7,7 +7,7 @@ namespace Persistence.API; /// /// Интерфейс для работы с API журнала изменений /// -public interface IChangeLogApi +public interface IChangeLogApi : ISyncWithDiscriminatorApi { /// /// Импорт с заменой: удаление старых строк и добавление новых diff --git a/Persistence/API/ISyncApi.cs b/Persistence/API/ISyncApi.cs index 7f72812..286df3d 100644 --- a/Persistence/API/ISyncApi.cs +++ b/Persistence/API/ISyncApi.cs @@ -6,7 +6,7 @@ namespace Persistence.API; /// /// Интерфейс для API, предназначенного для синхронизации данных /// -public interface ISyncApi where TDto : class, new() +public interface ISyncApi where TDto : class { /// /// Получить порцию записей, начиная с заданной даты diff --git a/Persistence/API/ISyncWithDiscriminatorApi.cs b/Persistence/API/ISyncWithDiscriminatorApi.cs new file mode 100644 index 0000000..c0c72f0 --- /dev/null +++ b/Persistence/API/ISyncWithDiscriminatorApi.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Mvc; +using Persistence.Models; + +namespace Persistence.API; + +/// +/// Интерфейс для API, предназначенного для синхронизации данных, у которых есть дискриминатор +/// +public interface ISyncWithDiscriminatorApi +{ + /// + /// Получить порцию записей, начиная с заданной даты + /// + /// + /// + /// количество записей + /// + /// + Task GetPart(Guid idDiscriminator, DateTimeOffset dateBegin, int take = 24 * 60 * 60, CancellationToken token = default); + + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// + /// + /// + /// + Task GetDatesRangeAsync(Guid idDiscriminator, CancellationToken token); +} diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index b5cd53a..c885c90 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -7,7 +7,7 @@ namespace Persistence.Repositories; /// Интерфейс для работы с историческими данными /// /// -public interface IChangeLogRepository //: ISyncRepository +public interface IChangeLogRepository : ISyncWithDiscriminatorRepository { /// /// Добавление записей diff --git a/Persistence/Repositories/ISyncRepository.cs b/Persistence/Repositories/ISyncRepository.cs index e18c5f5..5a5c9be 100644 --- a/Persistence/Repositories/ISyncRepository.cs +++ b/Persistence/Repositories/ISyncRepository.cs @@ -1,17 +1,25 @@ -namespace Persistence.Repositories; +using Persistence.Models; + +namespace Persistence.Repositories; /// /// Интерфейс по работе с данными /// /// public interface ISyncRepository - where TDto : class, new() { /// /// Получить данные, начиная с определенной даты /// /// дата начала + /// /// + Task> GetGtDate(DateTimeOffset dateBegin, CancellationToken token); + + + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// /// /// - Task> GetGtDate(DateTimeOffset dateBegin, CancellationToken token); + Task GetDatesRange(CancellationToken token); } diff --git a/Persistence/Repositories/ISyncWithDiscriminatorRepository.cs b/Persistence/Repositories/ISyncWithDiscriminatorRepository.cs new file mode 100644 index 0000000..7e0bd62 --- /dev/null +++ b/Persistence/Repositories/ISyncWithDiscriminatorRepository.cs @@ -0,0 +1,28 @@ +using Persistence.Models; + +namespace Persistence.Repositories; + +/// +/// Интерфейс по работе с данными, у которых есть дискриминатор +/// +/// +public interface ISyncWithDiscriminatorRepository +{ + /// + /// Получить данные, начиная с определенной даты + /// + /// дискриминатор таблицы + /// дата начала + /// + /// /// + Task> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token); + + + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// + /// дискриминатор таблицы + /// + /// + Task GetDatesRange(Guid idDiscriminator, CancellationToken token); +} diff --git a/Persistence/Repositories/ITimeSeriesBaseRepository.cs b/Persistence/Repositories/ITimeSeriesBaseRepository.cs index 7102d97..26edf2f 100644 --- a/Persistence/Repositories/ITimeSeriesBaseRepository.cs +++ b/Persistence/Repositories/ITimeSeriesBaseRepository.cs @@ -19,11 +19,4 @@ public interface ITimeSeriesBaseRepository double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default); - - /// - /// Получить диапазон дат, для которых есть данные в репозитории - /// - /// - /// - Task GetDatesRange(CancellationToken token); } -- 2.45.2 From 1e44e27b07694bb7361f42f6ce93e1fa4fb69106 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 2 Dec 2024 18:14:45 +0500 Subject: [PATCH 10/23] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 2 +- Persistence.API/DependencyInjection.cs | 12 +- Persistence.API/appsettings.json | 10 +- .../Clients/IChangeLogClient.cs | 121 ++++++++ Persistence.Client/Helpers/ApiTokenHelper.cs | 3 +- .../PersistenceDbContext.cs | 4 + .../Controllers/ChangeLogControllerTest.cs | 283 ++++++++++++++++++ .../Repositories/ChangeLogRepository.cs | 12 +- Persistence/Models/Requests/Request.cs | 2 +- 9 files changed, 439 insertions(+), 10 deletions(-) create mode 100644 Persistence.Client/Clients/IChangeLogClient.cs create mode 100644 Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index f65cbb1..63adaea 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -120,7 +120,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task GetByDate( Guid idDiscriminator, DateTimeOffset moment, - SectionPartRequest request, + [FromQuery] SectionPartRequest request, CancellationToken token) { var result = await repository.GetByDate(idDiscriminator, moment, request, token); diff --git a/Persistence.API/DependencyInjection.cs b/Persistence.API/DependencyInjection.cs index 81713e4..808d50e 100644 --- a/Persistence.API/DependencyInjection.cs +++ b/Persistence.API/DependencyInjection.cs @@ -1,5 +1,7 @@ +using System.Security.Claims; using System.Text.Json.Nodes; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; @@ -86,7 +88,7 @@ public static class DependencyInjection ValidAudience = JwtParams.Audience, ValidateLifetime = true, IssuerSigningKey = JwtParams.SecurityKey, - ValidateIssuerSigningKey = false + ValidateIssuerSigningKey = false, }; options.Events = new JwtBearerEvents { @@ -103,7 +105,13 @@ public static class DependencyInjection }, OnTokenValidated = context => { - var username = context.Principal?.Claims + if(context.Principal != null && context.Principal.HasClaim(x => x.Type != ClaimTypes.NameIdentifier)) + { + var claim = new Claim(ClaimTypes.NameIdentifier.ToString(), Guid.NewGuid().ToString()); + (context.Principal.Identity as ClaimsIdentity)!.AddClaim(claim); + } + + var username = context.Principal?.Claims .FirstOrDefault(e => e.Type == "username")?.Value; var password = context.Principal?.Claims diff --git a/Persistence.API/appsettings.json b/Persistence.API/appsettings.json index 3e1eea7..d4248fb 100644 --- a/Persistence.API/appsettings.json +++ b/Persistence.API/appsettings.json @@ -13,6 +13,14 @@ "MetadataAddress": "http://192.168.0.10:8321/realms/Persistence/.well-known/openid-configuration", "Audience": "account", "ValidIssuer": "http://192.168.0.10:8321/realms/Persistence", - "AuthorizationUrl": "http://192.168.0.10:8321/realms/Persistence/protocol/openid-connect/auth" + "AuthorizationUrl": "http://192.168.0.10:8321/realms/Persistence/protocol/openid-connect/auth" + }, + "NeedUseKeyCloak": false, + "AuthUser": { + "username": "myuser", + "password": 12345, + "clientId": "webapi", + "grantType": "password", + "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "7d9f3574-6574-4ca3-845a-0276eb4aa8f6" } } diff --git a/Persistence.Client/Clients/IChangeLogClient.cs b/Persistence.Client/Clients/IChangeLogClient.cs new file mode 100644 index 0000000..1658d5e --- /dev/null +++ b/Persistence.Client/Clients/IChangeLogClient.cs @@ -0,0 +1,121 @@ +using Microsoft.AspNetCore.Mvc; +using Persistence.Models; +using Persistence.Models.Requests; +using Refit; + +namespace Persistence.Client.Clients; + +/// +/// Интерфейс для тестирования API, предназначенного для работы с записями ChangeLod +/// +public interface IChangeLogClient +{ + private const string BaseRoute = "/api/ChangeLog"; + + //[Get($"{BaseRoute}/current")] + /// + /// Импорт с заменой: удаление старых строк и добавление новых + /// + /// + /// + /// + [Post($"{BaseRoute}/replace")] + Task> ClearAndInsertRange(Guid idDiscriminator, IEnumerable dtos); + + ///// + ///// Получение данных на текущую дату (с пагинацией) + ///// + ///// + ///// параметры запроса + ///// + ///// + //Task GetCurrent(Guid idDiscriminator, SectionPartRequest request, CancellationToken token); + + /// + /// Получение данных на определенную дату (с пагинацией) + /// + /// + /// + /// параметры запроса + /// + /// + [Get($"{BaseRoute}/moment")] + Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, [Query]SectionPartRequest request); + + /// + /// Получение исторических данных за определенный период времени + /// + /// + /// + /// + /// + /// + [Get($"{BaseRoute}/history")] + Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd); + + /// + /// Добавить одну запись + /// + /// + /// + /// + [Post($"{BaseRoute}")] + Task> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto); + + /// + /// Добавить несколько записей + /// + /// + /// + /// + /// + [Post($"{BaseRoute}/range")] + Task> AddRange(Guid idDiscriminator, IEnumerable dtos); + + /// + /// Обновить одну запись + /// + /// + /// + /// + [Put($"{BaseRoute}")] + Task> Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto); + + /// + /// Обновить несколько записей + /// + /// + /// + /// + /// + [Put($"{BaseRoute}/range")] + Task> UpdateRange(Guid idDiscriminator, IEnumerable dtos); + + /// + /// Удалить одну запись + /// + /// + /// + /// + [Delete($"{BaseRoute}")] + Task> Delete(Guid id); + + /// + /// Удалить несколько записей + /// + /// + /// + /// + [Delete($"{BaseRoute}/range")] + Task> DeleteRange([Body] IEnumerable ids); + + /// + /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) + /// + /// + /// + /// + [Get($"{BaseRoute}/datesRange")] + Task> GetDatesRange(Guid idDiscriminator); + +} diff --git a/Persistence.Client/Helpers/ApiTokenHelper.cs b/Persistence.Client/Helpers/ApiTokenHelper.cs index e508922..b61f86e 100644 --- a/Persistence.Client/Helpers/ApiTokenHelper.cs +++ b/Persistence.Client/Helpers/ApiTokenHelper.cs @@ -34,7 +34,8 @@ public static class ApiTokenHelper new("client_id", authUser.ClientId), new("username", authUser.Username), new("password", authUser.Password), - new("grant_type", authUser.GrantType) + new("grant_type", authUser.GrantType), + new(ClaimTypes.NameIdentifier.ToString(), Guid.NewGuid().ToString()) }; var tokenDescriptor = new SecurityTokenDescriptor diff --git a/Persistence.Database.Postgres/PersistenceDbContext.cs b/Persistence.Database.Postgres/PersistenceDbContext.cs index 0f7ba03..c122eb6 100644 --- a/Persistence.Database.Postgres/PersistenceDbContext.cs +++ b/Persistence.Database.Postgres/PersistenceDbContext.cs @@ -41,5 +41,9 @@ public partial class PersistenceDbContext : DbContext modelBuilder.Entity() .Property(e => e.Set) .HasJsonConversion(); + + modelBuilder.Entity() + .Property(e => e.Value) + .HasJsonConversion(); } } diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs new file mode 100644 index 0000000..a57433b --- /dev/null +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -0,0 +1,283 @@ +using Microsoft.Extensions.DependencyInjection; +using Persistence.Client.Clients; +using Persistence.Client; +using Persistence.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Net; +using Mapster; +using Persistence.Database.Model; +using Persistence.Models.Requests; + +namespace Persistence.IntegrationTests.Controllers; +public class ChangeLogControllerTest : BaseIntegrationTest +{ + private readonly IChangeLogClient client; + private static Random generatorRandomDigits = new Random(); + + public ChangeLogControllerTest(WebAppFactoryFixture factory) : base(factory) + { + var persistenceClientFactory = scope.ServiceProvider + .GetRequiredService(); + + client = persistenceClientFactory.GetClient(); + } + + [Fact] + public async Task ClearAndInsertRange() + { + // arrange + var idDiscriminator = Guid.NewGuid(); + var dtos = Generate(2, DateTimeOffset.UtcNow); + + // act + var result = await client.ClearAndInsertRange(idDiscriminator, dtos); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(2, result.Content); + } + + [Fact] + public async Task Add_returns_success() + { + // arrange + var count = 1; + var idDiscriminator = Guid.NewGuid(); + var dtos = Generate(count, DateTimeOffset.UtcNow); + var dto = dtos.FirstOrDefault()!; + + // act + var result = await client.Add(idDiscriminator, dto); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(count, result.Content); + } + + [Fact] + public async Task AddRange_returns_success() + { + // arrange + var count = 3; + var idDiscriminator = Guid.NewGuid(); + var dtos = Generate(count, DateTimeOffset.UtcNow); + + // act + var result = await client.AddRange(idDiscriminator, dtos); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(count, result.Content); + } + + [Fact] + public async Task Update_returns_success() + { + // arrange + var idDiscriminator = Guid.NewGuid(); + var dtos = Generate(1, DateTimeOffset.UtcNow); + var dto = dtos.FirstOrDefault()!; + var entity = dto.Adapt(); + dbContext.ChangeLog.Add(entity); + dbContext.SaveChanges(); + + dto.Id = entity.Id; + dto.DepthStart = dto.DepthStart + 10; + dto.DepthEnd = dto.DepthEnd + 10; + + // act + var result = await client.Update(idDiscriminator, dto); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(2, result.Content); + + //var entities = dbContext.ChangeLog + // .Where(e => e.IdDiscriminator == idDiscriminator) + // .ToArray(); + //var obsoleteEntity = entities + // .Where(e => e.Obsolete.HasValue) + // .FirstOrDefault(); + + //var activeEntity = entities + // .Where(e => !e.Obsolete.HasValue) + // .FirstOrDefault(); + + //if (obsoleteEntity == null || activeEntity == null) + //{ + // Assert.Fail(); + // return; + //} + + //Assert.Equal(activeEntity.IdNext, obsoleteEntity.Id); + + } + + [Fact] + public async Task UpdateRange_returns_success() + { + // arrange + var count = 2; + var idDiscriminator = Guid.NewGuid(); + var dtos = Generate(count, DateTimeOffset.UtcNow); + var entities = dtos.Select(d => d.Adapt()); + dbContext.ChangeLog.AddRange(entities); + dbContext.SaveChanges(); + + dtos = entities.Select(c => new DataWithWellDepthAndSectionDto() + { + DepthEnd = c.DepthEnd + 10, + DepthStart = c.DepthStart + 10, + Id = c.Id, + IdSection = c.IdSection, + Value = c.Value + }); + + // act + var result = await client.UpdateRange(idDiscriminator, dtos); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(count * 2, result.Content); + } + + [Fact] + public async Task Delete_returns_success() + { + // arrange + var dtos = Generate(1, DateTimeOffset.UtcNow); + var dto = dtos.FirstOrDefault()!; + var entity = dto.Adapt(); + dbContext.ChangeLog.Add(entity); + dbContext.SaveChanges(); + + // act + var result = await client.Delete(entity.Id); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(1, result.Content); + } + + [Fact] + public async Task DeleteRange_returns_success() + { + // arrange + var count = 10; + var dtos = Generate(count, DateTimeOffset.UtcNow); + var entities = dtos.Select(d => d.Adapt()).ToArray(); + dbContext.ChangeLog.AddRange(entities); + dbContext.SaveChanges(); + + // act + var ids = entities.Select(e => e.Id); + var result = await client.DeleteRange(ids); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(count, result.Content); + } + + [Fact] + public async Task GetDatesRange_returns_success() + { + // arrange + var changeLogItems = CreateChangeLogItems(3); + var idDiscriminator = changeLogItems.Item1; + var entities = changeLogItems.Item2; + + var orderedEntities = entities.OrderBy(e => e.Creation); + var minDate = orderedEntities.First().Creation; + var maxDate = orderedEntities.Last().Creation; + + // act + var result = await client.GetDatesRange(idDiscriminator); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.NotNull(result.Content); + + var expectedMinDate = minDate.ToUniversalTime().ToString(); + var actualMinDate = result.Content!.From.ToUniversalTime().ToString(); + Assert.Equal(expectedMinDate, actualMinDate); + + var expectedMaxDate = maxDate.ToUniversalTime().ToString(); + var actualMaxDate = result.Content!.To.ToUniversalTime().ToString(); + Assert.Equal(expectedMaxDate, actualMaxDate); + } + + private (Guid, ChangeLog[]) CreateChangeLogItems(int count) + { + Guid idDiscriminator = Guid.NewGuid(); + var dtos = Generate(count, DateTimeOffset.UtcNow); + var entities = dtos.Select(d => + { + var entity = d.Adapt(); + entity.IdDiscriminator = idDiscriminator; + entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(-15, 15)); + + return entity; + }).ToArray(); + dbContext.ChangeLog.AddRange(entities); + dbContext.SaveChanges(); + + return (idDiscriminator, entities); + } + + [Fact] + public async Task GetByDate_returns_success() + { + // arrange + var changeLogItems = CreateChangeLogItems(3); + var idDiscriminator = changeLogItems.Item1; + var entities = changeLogItems.Item2; + var createdDates = entities.Select(e => e.Creation); + + var dtos = entities.Select(e => + { + var dto = e.Adapt(); + dto.DepthEnd = dto.DepthEnd + 10; + + return dto; + }).ToArray(); + + var updatedItems = await client.UpdateRange(idDiscriminator, dtos); + + var request = new SectionPartRequest() { + Skip = 0, + Take = 10, + SortSettings = String.Empty, + }; + + var moment = DateTimeOffset.UtcNow.AddDays(20); + var result = await client.GetByDate(idDiscriminator, moment, request); + + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.NotNull(result.Content); + + } + + private static IEnumerable Generate(int count, DateTimeOffset from) + { + for (int i = 0; i < count; i++) + yield return new DataWithWellDepthAndSectionDto() + { + Value = new Dictionary() + { + { "Key", 1 } + }, + DepthStart = generatorRandomDigits.Next(1, 5), + DepthEnd = generatorRandomDigits.Next(5, 15), + Id = Guid.NewGuid(), + IdSection = Guid.NewGuid() + }; + + } +} diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 98ff7d3..7b92039 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -15,7 +15,7 @@ public class ChangeLogRepository : IChangeLogRepository this.db = db; } - public Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public async Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { foreach (var dto in dtos) { @@ -23,7 +23,7 @@ public class ChangeLogRepository : IChangeLogRepository db.Set().Add(entity); } - var result = db.SaveChangesAsync(token); + var result = await db.SaveChangesAsync(token); return result; } @@ -106,7 +106,7 @@ public class ChangeLogRepository : IChangeLogRepository updatedEntity.IdEditor = idUser; } - await db.SaveChangesAsync(token); + result = await db.SaveChangesAsync(token); await transaction.CommitAsync(token); return result; @@ -272,7 +272,11 @@ public class ChangeLogRepository : IChangeLogRepository public async Task GetDatesRange(Guid idDiscriminator, CancellationToken token) { - var query = this.db.Set().Where(e => e.IdDiscriminator == idDiscriminator); + var query = db.Set() + .Where(e => e.IdDiscriminator == idDiscriminator); + var test = db.Set().ToArray(); + var test2 = query.ToArray(); + var minDate = await query.MinAsync(o => o.Creation, token); var maxDate = await query.MaxAsync(o => o.Creation, token); diff --git a/Persistence/Models/Requests/Request.cs b/Persistence/Models/Requests/Request.cs index a53f5a9..c1b0583 100644 --- a/Persistence/Models/Requests/Request.cs +++ b/Persistence/Models/Requests/Request.cs @@ -21,5 +21,5 @@ public class Request /// Содержат список названий полей сортировки /// Указать направление сортировки можно через пробел "asc" или "desc" /// - public string SortSettings { get; set; } = string.Empty; + public string? SortSettings { get; set; } = string.Empty; } -- 2.45.2 From c3c04f9c66b8bf69aa744383f0f98243861b613f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 3 Dec 2024 11:35:58 +0500 Subject: [PATCH 11/23] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20changeLog=20(=D0=BE?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=87=D0=B0=D0=BD=D0=B8=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Clients/IChangeLogClient.cs | 25 +--- .../Controllers/ChangeLogControllerTest.cs | 136 +++++++++++------- 2 files changed, 92 insertions(+), 69 deletions(-) diff --git a/Persistence.Client/Clients/IChangeLogClient.cs b/Persistence.Client/Clients/IChangeLogClient.cs index 1658d5e..e904057 100644 --- a/Persistence.Client/Clients/IChangeLogClient.cs +++ b/Persistence.Client/Clients/IChangeLogClient.cs @@ -1,5 +1,4 @@ -using Microsoft.AspNetCore.Mvc; -using Persistence.Models; +using Persistence.Models; using Persistence.Models.Requests; using Refit; @@ -10,7 +9,7 @@ namespace Persistence.Client.Clients; /// public interface IChangeLogClient { - private const string BaseRoute = "/api/ChangeLog"; + private const string BaseRoute = "/api/ChangeLog"; //[Get($"{BaseRoute}/current")] /// @@ -22,25 +21,15 @@ public interface IChangeLogClient [Post($"{BaseRoute}/replace")] Task> ClearAndInsertRange(Guid idDiscriminator, IEnumerable dtos); - ///// - ///// Получение данных на текущую дату (с пагинацией) - ///// - ///// - ///// параметры запроса - ///// - ///// - //Task GetCurrent(Guid idDiscriminator, SectionPartRequest request, CancellationToken token); - /// - /// Получение данных на определенную дату (с пагинацией) + /// Получение актуальных данных на определенную дату (с пагинацией) /// /// /// /// параметры запроса - /// /// [Get($"{BaseRoute}/moment")] - Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, [Query]SectionPartRequest request); + Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, [Query] SectionPartRequest request); /// /// Получение исторических данных за определенный период времени @@ -48,7 +37,6 @@ public interface IChangeLogClient /// /// /// - /// /// [Get($"{BaseRoute}/history")] Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd); @@ -67,7 +55,6 @@ public interface IChangeLogClient /// /// /// - /// /// [Post($"{BaseRoute}/range")] Task> AddRange(Guid idDiscriminator, IEnumerable dtos); @@ -86,7 +73,6 @@ public interface IChangeLogClient /// /// /// - /// /// [Put($"{BaseRoute}/range")] Task> UpdateRange(Guid idDiscriminator, IEnumerable dtos); @@ -95,7 +81,6 @@ public interface IChangeLogClient /// Удалить одну запись /// /// - /// /// [Delete($"{BaseRoute}")] Task> Delete(Guid id); @@ -104,7 +89,6 @@ public interface IChangeLogClient /// Удалить несколько записей /// /// - /// /// [Delete($"{BaseRoute}/range")] Task> DeleteRange([Body] IEnumerable ids); @@ -113,7 +97,6 @@ public interface IChangeLogClient /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) /// /// - /// /// [Get($"{BaseRoute}/datesRange")] Task> GetDatesRange(Guid idDiscriminator); diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index a57433b..72f63da 100644 --- a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -1,19 +1,13 @@ -using Microsoft.Extensions.DependencyInjection; -using Persistence.Client.Clients; -using Persistence.Client; -using Persistence.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; -using Microsoft.AspNetCore.Mvc; +using Mapster; using Microsoft.EntityFrameworkCore; -using System.Net; -using Mapster; +using Microsoft.Extensions.DependencyInjection; +using Persistence.Client; +using Persistence.Client.Clients; using Persistence.Database.Model; +using Persistence.Models; using Persistence.Models.Requests; +using System.Net; +using Xunit; namespace Persistence.IntegrationTests.Controllers; public class ChangeLogControllerTest : BaseIntegrationTest @@ -58,7 +52,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); - Assert.Equal(count, result.Content); + Assert.Equal(count, result.Content); } [Fact] @@ -127,7 +121,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var count = 2; var idDiscriminator = Guid.NewGuid(); var dtos = Generate(count, DateTimeOffset.UtcNow); - var entities = dtos.Select(d => d.Adapt()); + var entities = dtos.Select(d => d.Adapt()).ToArray(); dbContext.ChangeLog.AddRange(entities); dbContext.SaveChanges(); @@ -138,7 +132,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest Id = c.Id, IdSection = c.IdSection, Value = c.Value - }); + }).ToArray(); // act var result = await client.UpdateRange(idDiscriminator, dtos); @@ -189,7 +183,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest public async Task GetDatesRange_returns_success() { // arrange - var changeLogItems = CreateChangeLogItems(3); + var changeLogItems = CreateChangeLogItems(3, (-15, 15)); var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2; @@ -213,57 +207,82 @@ public class ChangeLogControllerTest : BaseIntegrationTest Assert.Equal(expectedMaxDate, actualMaxDate); } - private (Guid, ChangeLog[]) CreateChangeLogItems(int count) - { - Guid idDiscriminator = Guid.NewGuid(); - var dtos = Generate(count, DateTimeOffset.UtcNow); - var entities = dtos.Select(d => - { - var entity = d.Adapt(); - entity.IdDiscriminator = idDiscriminator; - entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(-15, 15)); - - return entity; - }).ToArray(); - dbContext.ChangeLog.AddRange(entities); - dbContext.SaveChanges(); - - return (idDiscriminator, entities); - } - [Fact] public async Task GetByDate_returns_success() { // arrange - var changeLogItems = CreateChangeLogItems(3); + //создаем записи + var count = 5; + var changeLogItems = CreateChangeLogItems(count, (-15, 15)); var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2; - var createdDates = entities.Select(e => e.Creation); - var dtos = entities.Select(e => + //удаляем все созданные записи за исключением первой и второй + //даты 2-х оставшихся записей должны вернуться в методе GetByDate + var ids = entities.Select(e => e.Id); + var idsToDelete = ids.Skip(2); + + var deletedCount = await client.DeleteRange(idsToDelete); + + var request = new SectionPartRequest() { - var dto = e.Adapt(); - dto.DepthEnd = dto.DepthEnd + 10; - - return dto; - }).ToArray(); - - var updatedItems = await client.UpdateRange(idDiscriminator, dtos); - - var request = new SectionPartRequest() { Skip = 0, Take = 10, SortSettings = String.Empty, }; - var moment = DateTimeOffset.UtcNow.AddDays(20); + var moment = DateTimeOffset.UtcNow.AddDays(16); var result = await client.GetByDate(idDiscriminator, moment, request); Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result.Content); + var restEntities = entities.Where(e => !idsToDelete.Contains(e.Id)); + Assert.Equal(restEntities.Count(), result.Content.Count); + + var actualIds = restEntities.Select(e => e.Id); + var expectedIds = result.Content.Items.Select(e => e.Id); + Assert.Equivalent(expectedIds, actualIds); } + [Theory] + [InlineData(5, -15, 15, -20, 20, 10)] + [InlineData(5, -15, -10, -16, -9, 5)] + public async Task GetChangeLogForDate_returns_success( + int insertedCount, + int leftCreationFromCurrentDate, + int rightCreationFromCurrentDate, + int leftPointFromCurrentDate, + int rightPointFromCurrentDate, + int changeLogCount) + { + // arrange + //создаем записи + var count = insertedCount; + var daysRange = (leftCreationFromCurrentDate, rightCreationFromCurrentDate); + var changeLogItems = CreateChangeLogItems(count, daysRange); + var idDiscriminator = changeLogItems.Item1; + var entities = changeLogItems.Item2; + + foreach (var entity in entities) + { + entity.DepthEnd = entity.DepthEnd + 10; + } + var dtos = entities.Select(e => e.Adapt()).ToArray(); + await client.UpdateRange(idDiscriminator, dtos); + + //act + var dateBegin = DateTimeOffset.UtcNow.AddDays(leftPointFromCurrentDate); + var dateEnd = DateTimeOffset.UtcNow.AddDays(rightPointFromCurrentDate); + var result = await client.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd); + + //assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.NotNull(result.Content); + Assert.Equal(changeLogCount, result.Content.Count()); + } + + private static IEnumerable Generate(int count, DateTimeOffset from) { for (int i = 0; i < count; i++) @@ -280,4 +299,25 @@ public class ChangeLogControllerTest : BaseIntegrationTest }; } + + private (Guid, ChangeLog[]) CreateChangeLogItems(int count, (int, int) daysRange) + { + var minDayCount = daysRange.Item1; + var maxDayCount = daysRange.Item2; + + Guid idDiscriminator = Guid.NewGuid(); + var dtos = Generate(count, DateTimeOffset.UtcNow); + var entities = dtos.Select(d => + { + var entity = d.Adapt(); + entity.IdDiscriminator = idDiscriminator; + entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(minDayCount, maxDayCount)); + + return entity; + }).ToArray(); + dbContext.ChangeLog.AddRange(entities); + dbContext.SaveChanges(); + + return (idDiscriminator, entities); + } } -- 2.45.2 From e98cd7d6e9177d2fa5a2b22fc927582f910a8ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 3 Dec 2024 17:05:46 +0500 Subject: [PATCH 12/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 34 +- Persistence.API/DependencyInjection.cs | 294 +++++++++--------- .../DependencyInjection.cs | 8 +- .../Controllers/ChangeLogControllerTest.cs | 62 ++-- .../Repositories/ChangeLogRepository.cs | 27 +- Persistence/Models/ChangeLogDto.cs | 7 +- 6 files changed, 221 insertions(+), 211 deletions(-) diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 63adaea..bc66a16 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -29,24 +29,25 @@ public class ChangeLogController : ControllerBase, IChangeLogApi var userId = User.GetUserId(); var result = await repository.InsertRange(userId, idDiscriminator, [dto], token); - return Ok(result); + return CreatedAtAction(nameof(Add), result); } [HttpPost("range")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task AddRange( Guid idDiscriminator, - [FromBody] IEnumerable dtos, CancellationToken token) + [FromBody] IEnumerable dtos, + CancellationToken token = default) { var userId = User.GetUserId(); var result = await repository.InsertRange(userId, idDiscriminator, dtos, token); - return Ok(result); + return CreatedAtAction(nameof(AddRange), result); } [HttpDelete] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] - public async Task Delete(Guid id, CancellationToken token) + public async Task Delete(Guid id, CancellationToken token = default) { var userId = User.GetUserId(); var result = await repository.MarkAsDeleted(userId, [id], token); @@ -56,7 +57,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpDelete("range")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] - public async Task DeleteRange(IEnumerable ids, CancellationToken token) + public async Task DeleteRange(IEnumerable ids, CancellationToken token = default) { var userId = User.GetUserId(); var result = await repository.MarkAsDeleted(userId, ids, token); @@ -69,7 +70,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task ClearAndInsertRange( Guid idDiscriminator, IEnumerable dtos, - CancellationToken token) + CancellationToken token = default) { var userId = User.GetUserId(); var result = await repository.ClearAndInsertRange(userId, idDiscriminator, dtos, token); @@ -81,7 +82,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task Update( Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, - CancellationToken token) + CancellationToken token = default) { var userId = User.GetUserId(); var result = await repository.UpdateRange(userId, idDiscriminator, [dto], token); @@ -94,7 +95,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task UpdateRange( Guid idDiscriminator, IEnumerable dtos, - CancellationToken token) + CancellationToken token = default) { var userId = User.GetUserId(); var result = await repository.UpdateRange(userId, idDiscriminator, dtos, token); @@ -107,7 +108,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task GetCurrent( Guid idDiscriminator, [FromQuery]SectionPartRequest request, - CancellationToken token) + CancellationToken token = default) { var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); var result = await repository.GetByDate(idDiscriminator, moment, request, token); @@ -121,7 +122,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi Guid idDiscriminator, DateTimeOffset moment, [FromQuery] SectionPartRequest request, - CancellationToken token) + CancellationToken token = default) { var result = await repository.GetByDate(idDiscriminator, moment, request, token); @@ -130,7 +131,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("history")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + public async Task GetChangeLogForDate( + Guid idDiscriminator, + DateTimeOffset dateBegin, + DateTimeOffset dateEnd, + CancellationToken token = default) { var result = await repository.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd, token); @@ -139,7 +144,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("datesChange")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task GetDatesChange(Guid idDiscriminator, CancellationToken token) + public async Task GetDatesChange(Guid idDiscriminator, CancellationToken token = default) { var result = await repository.GetDatesChange(idDiscriminator, token); @@ -157,10 +162,13 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("datesRange")] [ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)] - public async Task GetDatesRangeAsync(Guid idDiscriminator, CancellationToken token) + public async Task GetDatesRangeAsync(Guid idDiscriminator, CancellationToken token = default) { var result = await repository.GetDatesRange(idDiscriminator, token); + if(result is null) + return NoContent(); + return Ok(result); } } diff --git a/Persistence.API/DependencyInjection.cs b/Persistence.API/DependencyInjection.cs index 808d50e..eebb665 100644 --- a/Persistence.API/DependencyInjection.cs +++ b/Persistence.API/DependencyInjection.cs @@ -1,12 +1,10 @@ -using System.Security.Claims; -using System.Text.Json.Nodes; using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; using Persistence.Models.Configurations; using Swashbuckle.AspNetCore.SwaggerGen; +using System.Text.Json.Nodes; namespace Persistence.API; @@ -35,169 +33,163 @@ public static class DependencyInjection c.SwaggerDoc("v1", new OpenApiInfo { Title = "Persistence web api", Version = "v1" }); - var needUseKeyCloak = configuration.GetSection("NeedUseKeyCloak").Get(); - if (needUseKeyCloak) - c.AddKeycloackSecurity(configuration); - else c.AddDefaultSecurity(configuration); + var needUseKeyCloak = configuration.GetSection("NeedUseKeyCloak").Get(); + if (needUseKeyCloak) + c.AddKeycloackSecurity(configuration); + else c.AddDefaultSecurity(configuration); - //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - //var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - //var includeControllerXmlComment = true; - //options.IncludeXmlComments(xmlPath, includeControllerXmlComment); - //options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment); - }); + //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + //var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + //var includeControllerXmlComment = true; + //c.IncludeXmlComments(xmlPath, includeControllerXmlComment); + //c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment); + }); } - #region Authentication - public static void AddJWTAuthentication(this IServiceCollection services, IConfiguration configuration) + #region Authentication + public static void AddJWTAuthentication(this IServiceCollection services, IConfiguration configuration) { var needUseKeyCloak = configuration - .GetSection("NeedUseKeyCloak") - .Get(); - if (needUseKeyCloak) - services.AddKeyCloakAuthentication(configuration); - else services.AddDefaultAuthentication(configuration); - } + .GetSection("NeedUseKeyCloak") + .Get(); + if (needUseKeyCloak) + services.AddKeyCloakAuthentication(configuration); + else services.AddDefaultAuthentication(configuration); + } - private static void AddKeyCloakAuthentication(this IServiceCollection services, IConfiguration configuration) - { + private static void AddKeyCloakAuthentication(this IServiceCollection services, IConfiguration configuration) + { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddJwtBearer(options => - { - options.RequireHttpsMetadata = false; - options.Audience = configuration["Authentication:Audience"]; - options.MetadataAddress = configuration["Authentication:MetadataAddress"]!; - options.TokenValidationParameters = new TokenValidationParameters - { - ValidIssuer = configuration["Authentication:ValidIssuer"], - }; + .AddJwtBearer(options => + { + options.RequireHttpsMetadata = false; + options.Audience = configuration["Authentication:Audience"]; + options.MetadataAddress = configuration["Authentication:MetadataAddress"]!; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidIssuer = configuration["Authentication:ValidIssuer"], + }; }); - } + } - private static void AddDefaultAuthentication(this IServiceCollection services, IConfiguration configuration) - { - services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddJwtBearer(options => - { - options.RequireHttpsMetadata = false; - options.TokenValidationParameters = new TokenValidationParameters - { - ValidateIssuer = true, - ValidIssuer = JwtParams.Issuer, - ValidateAudience = true, - ValidAudience = JwtParams.Audience, - ValidateLifetime = true, - IssuerSigningKey = JwtParams.SecurityKey, - ValidateIssuerSigningKey = false, - }; - options.Events = new JwtBearerEvents - { - OnMessageReceived = context => - { - var accessToken = context.Request.Headers["Authorization"] - .ToString() - .Replace(JwtBearerDefaults.AuthenticationScheme, string.Empty) - .Trim(); + private static void AddDefaultAuthentication(this IServiceCollection services, IConfiguration configuration) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.RequireHttpsMetadata = false; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidIssuer = JwtParams.Issuer, + ValidateAudience = true, + ValidAudience = JwtParams.Audience, + ValidateLifetime = true, + IssuerSigningKey = JwtParams.SecurityKey, + ValidateIssuerSigningKey = false, + }; + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + var accessToken = context.Request.Headers["Authorization"] + .ToString() + .Replace(JwtBearerDefaults.AuthenticationScheme, string.Empty) + .Trim(); - context.Token = accessToken; + context.Token = accessToken; - return Task.CompletedTask; - }, - OnTokenValidated = context => - { - if(context.Principal != null && context.Principal.HasClaim(x => x.Type != ClaimTypes.NameIdentifier)) - { - var claim = new Claim(ClaimTypes.NameIdentifier.ToString(), Guid.NewGuid().ToString()); - (context.Principal.Identity as ClaimsIdentity)!.AddClaim(claim); + return Task.CompletedTask; + }, + OnTokenValidated = context => + { + var username = context.Principal?.Claims + .FirstOrDefault(e => e.Type == "username")?.Value; + + var password = context.Principal?.Claims + .FirstOrDefault(e => e.Type == "password")?.Value; + + var keyCloakUser = configuration + .GetSection(nameof(AuthUser)) + .Get()!; + + if (username != keyCloakUser.Username || password != keyCloakUser.Password) + { + context.Fail("username or password did not match"); } - var username = context.Principal?.Claims - .FirstOrDefault(e => e.Type == "username")?.Value; + return Task.CompletedTask; + } + }; + }); + } + #endregion - var password = context.Principal?.Claims - .FirstOrDefault(e => e.Type == "password")?.Value; + #region Security (Swagger) + private static void AddKeycloackSecurity(this SwaggerGenOptions options, IConfiguration configuration) + { + options.AddSecurityDefinition("Keycloack", new OpenApiSecurityScheme + { + Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows + { + Implicit = new OpenApiOAuthFlow + { + AuthorizationUrl = new Uri(configuration["Authentication:AuthorizationUrl"]), + } + } + }); - var keyCloakUser = configuration - .GetSection(nameof(AuthUser)) - .Get()!; + options.AddSecurityRequirement(new OpenApiSecurityRequirement() + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Keycloack" + }, + Scheme = "Bearer", + Name = "Bearer", + In = ParameterLocation.Header, + }, + new List() + } + }); + } - if (username != keyCloakUser.Username || password != keyCloakUser.Password) - { - context.Fail("username or password did not match"); - } + private static void AddDefaultSecurity(this SwaggerGenOptions options, IConfiguration configuration) + { + options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey, + Scheme = "Bearer", + }); - return Task.CompletedTask; - } - }; - }); - } - #endregion - - #region Security (Swagger) - private static void AddKeycloackSecurity(this SwaggerGenOptions options, IConfiguration configuration) - { - options.AddSecurityDefinition("Keycloack", new OpenApiSecurityScheme - { - Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows - { - Implicit = new OpenApiOAuthFlow - { - AuthorizationUrl = new Uri(configuration["Authentication:AuthorizationUrl"]), - } - } - }); - - options.AddSecurityRequirement(new OpenApiSecurityRequirement() - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "Keycloack" - }, - Scheme = "Bearer", - Name = "Bearer", - In = ParameterLocation.Header, - }, - new List() - } - }); - } - - private static void AddDefaultSecurity(this SwaggerGenOptions options, IConfiguration configuration) - { - options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - { - Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.ApiKey, - Scheme = "Bearer", - }); - - options.AddSecurityRequirement(new OpenApiSecurityRequirement() - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "Bearer" - }, - Scheme = "oauth2", - Name = "Bearer", - In = ParameterLocation.Header, - }, - new List() - } - }); - } - #endregion + options.AddSecurityRequirement(new OpenApiSecurityRequirement() + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + }, + Scheme = "oauth2", + Name = "Bearer", + In = ParameterLocation.Header, + }, + new List() + } + }); + } + #endregion } diff --git a/Persistence.Database.Postgres/DependencyInjection.cs b/Persistence.Database.Postgres/DependencyInjection.cs index 0fec635..bbd936b 100644 --- a/Persistence.Database.Postgres/DependencyInjection.cs +++ b/Persistence.Database.Postgres/DependencyInjection.cs @@ -11,12 +11,8 @@ public static class DependencyInjection { string connectionStringName = "DefaultConnection"; - services.AddDbContext(options => - { - var dataSourceBuilder = new NpgsqlDataSourceBuilder(configuration.GetConnectionString(connectionStringName)); - dataSourceBuilder.EnableDynamicJson(); - options.UseNpgsql(dataSourceBuilder.Build()); - }); + services.AddDbContext(options => + options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); services.AddScoped(provider => provider.GetRequiredService()); diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index 72f63da..39ea3f8 100644 --- a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -78,39 +78,46 @@ public class ChangeLogControllerTest : BaseIntegrationTest var idDiscriminator = Guid.NewGuid(); var dtos = Generate(1, DateTimeOffset.UtcNow); var dto = dtos.FirstOrDefault()!; - var entity = dto.Adapt(); - dbContext.ChangeLog.Add(entity); - dbContext.SaveChanges(); + var result = await client.Add(idDiscriminator, dto); + Assert.Equal(HttpStatusCode.OK, result.StatusCode); - dto.Id = entity.Id; - dto.DepthStart = dto.DepthStart + 10; + var entity = dbContext.ChangeLog + .Where(x => x.IdDiscriminator == idDiscriminator) + .FirstOrDefault(); + dto = entity.Adapt(); dto.DepthEnd = dto.DepthEnd + 10; // act - var result = await client.Update(idDiscriminator, dto); + result = await client.Update(idDiscriminator, dto); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(2, result.Content); - //var entities = dbContext.ChangeLog - // .Where(e => e.IdDiscriminator == idDiscriminator) - // .ToArray(); - //var obsoleteEntity = entities - // .Where(e => e.Obsolete.HasValue) - // .FirstOrDefault(); + var dateBegin = DateTimeOffset.UtcNow.AddDays(-1); + var dateEnd = DateTimeOffset.UtcNow.AddDays(1); - //var activeEntity = entities - // .Where(e => !e.Obsolete.HasValue) - // .FirstOrDefault(); + var changeLogResult = await client.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd); + Assert.Equal(HttpStatusCode.OK, changeLogResult.StatusCode); + Assert.NotNull(changeLogResult.Content); - //if (obsoleteEntity == null || activeEntity == null) - //{ - // Assert.Fail(); - // return; - //} + var changeLogDtos = changeLogResult.Content; - //Assert.Equal(activeEntity.IdNext, obsoleteEntity.Id); + var obsoleteDto = changeLogDtos + .Where(e => e.Obsolete.HasValue) + .FirstOrDefault(); + + var activeDto = changeLogDtos + .Where(e => !e.Obsolete.HasValue) + .FirstOrDefault(); + + if (obsoleteDto == null || activeDto == null) + { + Assert.Fail(); + return; + } + + Assert.Equal(activeDto.Id, obsoleteDto.IdNext); } @@ -185,11 +192,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest // arrange var changeLogItems = CreateChangeLogItems(3, (-15, 15)); var idDiscriminator = changeLogItems.Item1; - var entities = changeLogItems.Item2; - - var orderedEntities = entities.OrderBy(e => e.Creation); - var minDate = orderedEntities.First().Creation; - var maxDate = orderedEntities.Last().Creation; + var entities = changeLogItems.Item2.OrderBy(e => e.Creation); // act var result = await client.GetDatesRange(idDiscriminator); @@ -198,12 +201,15 @@ public class ChangeLogControllerTest : BaseIntegrationTest Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result.Content); + var minDate = entities.First().Creation; + var maxDate = entities.Last().Creation; + var expectedMinDate = minDate.ToUniversalTime().ToString(); - var actualMinDate = result.Content!.From.ToUniversalTime().ToString(); + var actualMinDate = result.Content.From.ToUniversalTime().ToString(); Assert.Equal(expectedMinDate, actualMinDate); var expectedMaxDate = maxDate.ToUniversalTime().ToString(); - var actualMaxDate = result.Content!.To.ToUniversalTime().ToString(); + var actualMaxDate = result.Content.To.ToUniversalTime().ToString(); Assert.Equal(expectedMaxDate, actualMaxDate); } diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 7b92039..514fed5 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -232,11 +232,6 @@ public class ChangeLogRepository : IChangeLogRepository return datesOnly; } - public Task>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token) - { - throw new NotImplementedException(); - } - private ChangeLog CreateEntityFromDto(Guid idUser, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) { var entity = new ChangeLog() @@ -273,17 +268,25 @@ public class ChangeLogRepository : IChangeLogRepository public async Task GetDatesRange(Guid idDiscriminator, CancellationToken token) { var query = db.Set() - .Where(e => e.IdDiscriminator == idDiscriminator); - var test = db.Set().ToArray(); - var test2 = query.ToArray(); + .Where(e => e.IdDiscriminator == idDiscriminator) + .GroupBy(e => 1) + .Select(group => new + { + Min = group.Min(e => e.Creation), + Max = group.Max(e => e.Creation), + }); - var minDate = await query.MinAsync(o => o.Creation, token); - var maxDate = await query.MaxAsync(o => o.Creation, token); + var values = await query.FirstOrDefaultAsync(token); + + if(values is null) + { + return null; + } return new DatesRangeDto { - From = minDate, - To = maxDate + From = values.Min, + To = values.Max, }; } } diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index aa8963f..8e28874 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -10,6 +10,11 @@ public class ChangeLogDto } + /// + /// Ключ записи + /// + public Guid Id { get; set; } + /// /// Создатель записи /// @@ -38,5 +43,5 @@ public class ChangeLogDto /// /// Объект записи /// - public DataWithWellDepthAndSectionDto Value { get; set; } + public DataWithWellDepthAndSectionDto Value { get; set; } = default!; } -- 2.45.2 From ca816da076ff15b18b258efed638258888d47daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 3 Dec 2024 17:36:41 +0500 Subject: [PATCH 13/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20(=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B8=D1=87=D0=BD=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 2 +- .../Clients/IChangeLogClient.cs | 3 +- .../Controllers/ChangeLogControllerTest.cs | 6 +-- .../Repositories/ChangeLogRepository.cs | 6 +-- Persistence/Models/ChangeLogDto.cs | 2 +- .../Models/DataWithWellDepthAndSectionDto.cs | 7 +--- Persistence/Models/IChangeLogDto.cs | 42 ------------------- Persistence/Models/ProcessMapRotorDto.cs | 11 ----- Persistence/Models/Requests/Request.cs | 6 +-- .../Repositories/IChangeLogRepository.cs | 2 +- 10 files changed, 14 insertions(+), 73 deletions(-) delete mode 100644 Persistence/Models/IChangeLogDto.cs delete mode 100644 Persistence/Models/ProcessMapRotorDto.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index bc66a16..a698b87 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -137,7 +137,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi DateTimeOffset dateEnd, CancellationToken token = default) { - var result = await repository.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd, token); + var result = await repository.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, token); return Ok(result); } diff --git a/Persistence.Client/Clients/IChangeLogClient.cs b/Persistence.Client/Clients/IChangeLogClient.cs index e904057..74807cc 100644 --- a/Persistence.Client/Clients/IChangeLogClient.cs +++ b/Persistence.Client/Clients/IChangeLogClient.cs @@ -11,7 +11,6 @@ public interface IChangeLogClient { private const string BaseRoute = "/api/ChangeLog"; - //[Get($"{BaseRoute}/current")] /// /// Импорт с заменой: удаление старых строк и добавление новых /// @@ -39,7 +38,7 @@ public interface IChangeLogClient /// /// [Get($"{BaseRoute}/history")] - Task>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd); + Task>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd); /// /// Добавить одну запись diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index 39ea3f8..ea47c6a 100644 --- a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -97,7 +97,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var dateBegin = DateTimeOffset.UtcNow.AddDays(-1); var dateEnd = DateTimeOffset.UtcNow.AddDays(1); - var changeLogResult = await client.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd); + var changeLogResult = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); Assert.Equal(HttpStatusCode.OK, changeLogResult.StatusCode); Assert.NotNull(changeLogResult.Content); @@ -254,7 +254,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest [Theory] [InlineData(5, -15, 15, -20, 20, 10)] [InlineData(5, -15, -10, -16, -9, 5)] - public async Task GetChangeLogForDate_returns_success( + public async Task GetChangeLogForInterval_returns_success( int insertedCount, int leftCreationFromCurrentDate, int rightCreationFromCurrentDate, @@ -280,7 +280,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest //act var dateBegin = DateTimeOffset.UtcNow.AddDays(leftPointFromCurrentDate); var dateEnd = DateTimeOffset.UtcNow.AddDays(rightPointFromCurrentDate); - var result = await client.GetChangeLogForDate(idDiscriminator, dateBegin, dateEnd); + var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); //assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 514fed5..09c304a 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -153,7 +153,7 @@ public class ChangeLogRepository : IChangeLogRepository return query; } - public async Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) + public async Task> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) { var query = db.Set().Where(s => s.IdDiscriminator == idDiscriminator); @@ -177,8 +177,8 @@ public class ChangeLogRepository : IChangeLogRepository { var result = new PaginationContainer { - Skip = request.Skip ?? 0, - Take = request.Take ?? 32, + Skip = request.Skip, + Take = request.Take, Items = Enumerable.Empty(), Count = await query.CountAsync(token) }; diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index 8e28874..ba3ff5c 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -36,7 +36,7 @@ public class ChangeLogDto public DateTimeOffset? Obsolete { get; set; } /// - /// Ключ следующей записи + /// Ключ заменившей записи /// public Guid? IdNext { get; set; } diff --git a/Persistence/Models/DataWithWellDepthAndSectionDto.cs b/Persistence/Models/DataWithWellDepthAndSectionDto.cs index b3747c2..7939dd0 100644 --- a/Persistence/Models/DataWithWellDepthAndSectionDto.cs +++ b/Persistence/Models/DataWithWellDepthAndSectionDto.cs @@ -11,11 +11,6 @@ namespace Persistence.Models; /// public class DataWithWellDepthAndSectionDto { - public DataWithWellDepthAndSectionDto() - { - - } - /// /// Ключ записи /// @@ -39,5 +34,5 @@ public class DataWithWellDepthAndSectionDto /// /// Объект записи /// - public required IDictionary Value { get; set; } = default!; + public required IDictionary Value { get; set; } } diff --git a/Persistence/Models/IChangeLogDto.cs b/Persistence/Models/IChangeLogDto.cs deleted file mode 100644 index 09cfd09..0000000 --- a/Persistence/Models/IChangeLogDto.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Persistence.Models; - -/// -/// Часть записи описывающая изменение -/// -public interface IChangeLogDto -{ - ///// - ///// Ид записи - ///// - //public int Id { get; set; } - - ///// - ///// Автор изменения - ///// - //public int IdAuthor { get; set; } - - ///// - ///// Редактор - ///// - //public int? IdEditor { get; set; } - - ///// - ///// Дата создания записи - ///// - //public DateTimeOffset Creation { get; set; } - - ///// - ///// Дата устаревания (например при удалении) - ///// - //public DateTimeOffset? Obsolete { get; set; } - - ///// - ///// Id заменяющей записи - ///// - //public int? IdNext { get; set; } - - ///// - ///// Значение - ///// - //public object Value { get; set; } -} diff --git a/Persistence/Models/ProcessMapRotorDto.cs b/Persistence/Models/ProcessMapRotorDto.cs deleted file mode 100644 index 316f07a..0000000 --- a/Persistence/Models/ProcessMapRotorDto.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Persistence.Models; -public class ProcessMapRotorDto : IChangeLogDto -{ - public string Caption { get; set; } -} diff --git a/Persistence/Models/Requests/Request.cs b/Persistence/Models/Requests/Request.cs index c1b0583..30dd38a 100644 --- a/Persistence/Models/Requests/Request.cs +++ b/Persistence/Models/Requests/Request.cs @@ -9,17 +9,17 @@ public class Request /// /// Кол-во записей пропущенных с начала таблицы в запросе от api /// - public int? Skip { get; set; } + public int Skip { get; set; } = 0; /// /// Кол-во записей в запросе от api /// - public int? Take { get; set; } + public int Take { get; set; } = 32; /// /// Сортировки: /// Содержат список названий полей сортировки /// Указать направление сортировки можно через пробел "asc" или "desc" /// - public string? SortSettings { get; set; } = string.Empty; + public string? SortSettings { get; set; } } diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index c885c90..2d668cc 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -75,7 +75,7 @@ public interface IChangeLogRepository : ISyncWithDiscriminatorRepository /// /// - Task> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); + Task> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); /// /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) -- 2.45.2 From 6447b5e94fc1f484cf4b03507dd039696bb607b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Thu, 5 Dec 2024 11:01:00 +0500 Subject: [PATCH 14/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= =?UTF-8?q?=20(=D0=BE=D0=BA=D0=BE=D0=BD=D1=87=D0=B0=D0=BD=D0=B8=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 24 +-- .../Clients/IChangeLogClient.cs | 11 +- .../Controllers/ChangeLogControllerTest.cs | 32 ++-- .../Repositories/ChangeLogRepository.cs | 50 +++--- Persistence/API/IChangeLogApi.cs | 18 +- Persistence/API/ITableDataApi.cs | 2 +- .../{Request.cs => PaginationRequest.cs} | 2 +- .../Models/Requests/SectionPartRequest.cs | 2 +- .../AbstractChangeLogRepository.cs | 165 ------------------ .../Repositories/IChangeLogRepository.cs | 26 +-- .../Repositories/ITableDataRepository.cs | 2 +- 11 files changed, 93 insertions(+), 241 deletions(-) rename Persistence/Models/Requests/{Request.cs => PaginationRequest.cs} (96%) delete mode 100644 Persistence/Repositories/AbstractChangeLogRepository.cs diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index a698b87..233af58 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -27,7 +27,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi CancellationToken token) { var userId = User.GetUserId(); - var result = await repository.InsertRange(userId, idDiscriminator, [dto], token); + var result = await repository.AddRange(userId, idDiscriminator, [dto], token); return CreatedAtAction(nameof(Add), result); } @@ -40,7 +40,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi CancellationToken token = default) { var userId = User.GetUserId(); - var result = await repository.InsertRange(userId, idDiscriminator, dtos, token); + var result = await repository.AddRange(userId, idDiscriminator, dtos, token); return CreatedAtAction(nameof(AddRange), result); } @@ -67,25 +67,24 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpPost("replace")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] - public async Task ClearAndInsertRange( + public async Task ClearAndAddRange( Guid idDiscriminator, IEnumerable dtos, CancellationToken token = default) { var userId = User.GetUserId(); - var result = await repository.ClearAndInsertRange(userId, idDiscriminator, dtos, token); + var result = await repository.ClearAndAddRange(userId, idDiscriminator, dtos, token); return Ok(result); } [HttpPut] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task Update( - Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token = default) { var userId = User.GetUserId(); - var result = await repository.UpdateRange(userId, idDiscriminator, [dto], token); + var result = await repository.UpdateRange(userId, [dto], token); return Ok(result); } @@ -93,12 +92,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpPut("range")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task UpdateRange( - Guid idDiscriminator, IEnumerable dtos, CancellationToken token = default) { var userId = User.GetUserId(); - var result = await repository.UpdateRange(userId, idDiscriminator, dtos, token); + var result = await repository.UpdateRange(userId, dtos, token); return Ok(result); } @@ -107,11 +105,12 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetCurrent( Guid idDiscriminator, - [FromQuery]SectionPartRequest request, + [FromQuery]SectionPartRequest filterRequest, + [FromQuery] PaginationRequest paginationRequest, CancellationToken token = default) { var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); - var result = await repository.GetByDate(idDiscriminator, moment, request, token); + var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token); return Ok(result); } @@ -121,10 +120,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task GetByDate( Guid idDiscriminator, DateTimeOffset moment, - [FromQuery] SectionPartRequest request, + [FromQuery] SectionPartRequest filterRequest, + [FromQuery] PaginationRequest paginationRequest, CancellationToken token = default) { - var result = await repository.GetByDate(idDiscriminator, moment, request, token); + var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token); return Ok(result); } diff --git a/Persistence.Client/Clients/IChangeLogClient.cs b/Persistence.Client/Clients/IChangeLogClient.cs index 74807cc..4f1cc60 100644 --- a/Persistence.Client/Clients/IChangeLogClient.cs +++ b/Persistence.Client/Clients/IChangeLogClient.cs @@ -18,17 +18,22 @@ public interface IChangeLogClient /// /// [Post($"{BaseRoute}/replace")] - Task> ClearAndInsertRange(Guid idDiscriminator, IEnumerable dtos); + Task> ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos); /// /// Получение актуальных данных на определенную дату (с пагинацией) /// /// /// - /// параметры запроса + /// параметры запроса фильтрации + /// параметры запроса пагинации /// [Get($"{BaseRoute}/moment")] - Task>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, [Query] SectionPartRequest request); + Task>> GetByDate( + Guid idDiscriminator, + DateTimeOffset moment, + [Query] SectionPartRequest filterRequest, + [Query] PaginationRequest paginationRequest); /// /// Получение исторических данных за определенный период времени diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index ea47c6a..0f24bb8 100644 --- a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -31,7 +31,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var dtos = Generate(2, DateTimeOffset.UtcNow); // act - var result = await client.ClearAndInsertRange(idDiscriminator, dtos); + var result = await client.ClearAndAddRange(idDiscriminator, dtos); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); @@ -51,7 +51,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var result = await client.Add(idDiscriminator, dto); // assert - Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(HttpStatusCode.Created, result.StatusCode); Assert.Equal(count, result.Content); } @@ -67,7 +67,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var result = await client.AddRange(idDiscriminator, dtos); // assert - Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(HttpStatusCode.Created, result.StatusCode); Assert.Equal(count, result.Content); } @@ -79,7 +79,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var dtos = Generate(1, DateTimeOffset.UtcNow); var dto = dtos.FirstOrDefault()!; var result = await client.Add(idDiscriminator, dto); - Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(HttpStatusCode.Created, result.StatusCode); var entity = dbContext.ChangeLog .Where(x => x.IdDiscriminator == idDiscriminator) @@ -230,7 +230,13 @@ public class ChangeLogControllerTest : BaseIntegrationTest var deletedCount = await client.DeleteRange(idsToDelete); - var request = new SectionPartRequest() + var filterRequest = new SectionPartRequest() + { + DepthStart = 0, + DepthEnd = 1000, + }; + + var paginationRequest = new PaginationRequest() { Skip = 0, Take = 10, @@ -238,7 +244,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest }; var moment = DateTimeOffset.UtcNow.AddDays(16); - var result = await client.GetByDate(idDiscriminator, moment, request); + var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest); Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.NotNull(result.Content); @@ -256,16 +262,16 @@ public class ChangeLogControllerTest : BaseIntegrationTest [InlineData(5, -15, -10, -16, -9, 5)] public async Task GetChangeLogForInterval_returns_success( int insertedCount, - int leftCreationFromCurrentDate, - int rightCreationFromCurrentDate, - int leftPointFromCurrentDate, - int rightPointFromCurrentDate, + int daysBeforeNowChangeLog, + int daysAfterNowChangeLog, + int daysBeforeNowFilter, + int daysAfterNowFilter, int changeLogCount) { // arrange //создаем записи var count = insertedCount; - var daysRange = (leftCreationFromCurrentDate, rightCreationFromCurrentDate); + var daysRange = (daysBeforeNowChangeLog, daysAfterNowChangeLog); var changeLogItems = CreateChangeLogItems(count, daysRange); var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2; @@ -278,8 +284,8 @@ public class ChangeLogControllerTest : BaseIntegrationTest await client.UpdateRange(idDiscriminator, dtos); //act - var dateBegin = DateTimeOffset.UtcNow.AddDays(leftPointFromCurrentDate); - var dateEnd = DateTimeOffset.UtcNow.AddDays(rightPointFromCurrentDate); + var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter); + var dateEnd = DateTimeOffset.UtcNow.AddDays(daysAfterNowFilter); var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); //assert diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 09c304a..07159d7 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -15,11 +15,11 @@ public class ChangeLogRepository : IChangeLogRepository this.db = db; } - public async Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public async Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { foreach (var dto in dtos) { - var entity = CreateEntityFromDto(idUser, idDiscriminator, dto); + var entity = CreateEntityFromDto(idAuthor, idDiscriminator, dto); db.Set().Add(entity); } @@ -28,49 +28,49 @@ public class ChangeLogRepository : IChangeLogRepository return result; } - public async Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token) + public async Task MarkAsDeleted(Guid idEditor, IEnumerable ids, CancellationToken token) { var query = db.Set().Where(s => ids.Contains(s.Id)); var entities = await query.ToArrayAsync(token); - var result = await Clear(idUser, entities, token); + var result = await Clear(idEditor, entities, token); return result; } - public async Task MarkAsDeleted(Guid idUser, Guid idDiscriminator, CancellationToken token) + public async Task MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token) { var query = db.Set() .Where(s => s.IdDiscriminator == idDiscriminator) .Where(e => e.Obsolete == null); var entities = await query.ToArrayAsync(token); - var result = await Clear(idUser, entities, token); + var result = await Clear(idEditor, entities, token); return result; } - private async Task Clear(Guid idUser, IEnumerable entities, CancellationToken token) + private async Task Clear(Guid idEditor, IEnumerable entities, CancellationToken token) { var updateTime = DateTimeOffset.UtcNow; foreach (var entity in entities) { entity.Obsolete = updateTime; - entity.IdEditor = idUser; + entity.IdEditor = idEditor; } return await db.SaveChangesAsync(token); } - public async Task ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public async Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var result = 0; using var transaction = await db.Database.BeginTransactionAsync(token); try { - result += await MarkAsDeleted(idUser, idDiscriminator, token); - result += await InsertRange(idUser, idDiscriminator, dtos, token); + result += await MarkAsDeleted(idAuthor, idDiscriminator, token); + result += await AddRange(idAuthor, idDiscriminator, dtos, token); await transaction.CommitAsync(token); return result; @@ -82,7 +82,7 @@ public class ChangeLogRepository : IChangeLogRepository } } - public async Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public async Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token) { var dbSet = db.Set(); @@ -97,13 +97,18 @@ public class ChangeLogRepository : IChangeLogRepository { foreach (var dto in dtos) { - var newEntity = CreateEntityFromDto(idUser, idDiscriminator, dto); + var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id); + if(updatedEntity is null) + { + throw new ArgumentNullException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); + } + + var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto); dbSet.Add(newEntity); - var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id)!; updatedEntity.IdNext = newEntity.Id; updatedEntity.Obsolete = DateTimeOffset.UtcNow; - updatedEntity.IdEditor = idUser; + updatedEntity.IdEditor = idEditor; } result = await db.SaveChangesAsync(token); @@ -121,11 +126,12 @@ public class ChangeLogRepository : IChangeLogRepository public async Task> GetByDate( Guid idDiscriminator, DateTimeOffset momentUtc, - SectionPartRequest request, + SectionPartRequest filterRequest, + PaginationRequest paginationRequest, CancellationToken token) { - var query = BuildQuery(idDiscriminator, momentUtc, request); - var result = await BuildPaginationContainer(query, request, token); + var query = BuildQuery(idDiscriminator, momentUtc, filterRequest); + var result = await BuildPaginationContainer(query, paginationRequest, token); return result; } @@ -173,7 +179,7 @@ public class ChangeLogRepository : IChangeLogRepository - private async Task> BuildPaginationContainer(IQueryable query, SectionPartRequest request, CancellationToken token) + private async Task> BuildPaginationContainer(IQueryable query, PaginationRequest request, CancellationToken token) { var result = new PaginationContainer { @@ -232,15 +238,15 @@ public class ChangeLogRepository : IChangeLogRepository return datesOnly; } - private ChangeLog CreateEntityFromDto(Guid idUser, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) + private ChangeLog CreateEntityFromDto(Guid idAuthor, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) { var entity = new ChangeLog() { Id = default, Creation = DateTimeOffset.UtcNow, - IdAuthor = idUser, + IdAuthor = idAuthor, IdDiscriminator = idDiscriminator, - IdEditor = idUser, + IdEditor = idAuthor, Value = dto.Value, IdSection = dto.IdSection, diff --git a/Persistence/API/IChangeLogApi.cs b/Persistence/API/IChangeLogApi.cs index 40ca8ae..25b5158 100644 --- a/Persistence/API/IChangeLogApi.cs +++ b/Persistence/API/IChangeLogApi.cs @@ -16,26 +16,28 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// /// - Task ClearAndInsertRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Получение данных на текущую дату (с пагинацией) /// /// - /// параметры запроса + /// параметры запроса фильтрации + /// параметры запроса пагинации /// /// - Task GetCurrent(Guid idDiscriminator, SectionPartRequest request, CancellationToken token); + Task GetCurrent(Guid idDiscriminator, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение данных на определенную дату (с пагинацией) /// /// /// - /// параметры запроса + /// параметры запроса фильтрации + /// параметры запроса пагинации /// /// - Task GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); + Task GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение исторических данных за определенный период времени @@ -68,20 +70,18 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// Обновить одну запись /// - /// /// /// /// - Task Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Update(DataWithWellDepthAndSectionDto dto, CancellationToken token); /// /// Обновить несколько записей /// - /// /// /// /// - Task UpdateRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task UpdateRange(IEnumerable dtos, CancellationToken token); /// /// Удалить одну запись diff --git a/Persistence/API/ITableDataApi.cs b/Persistence/API/ITableDataApi.cs index 075559a..e5611a4 100644 --- a/Persistence/API/ITableDataApi.cs +++ b/Persistence/API/ITableDataApi.cs @@ -7,7 +7,7 @@ namespace Persistence.API; /// Интерфейс для API, предназначенного для работы с табличными данными public interface ITableDataApi where TDto : class, new() - where TRequest : Request + where TRequest : PaginationRequest { /// /// Получить страницу списка объектов diff --git a/Persistence/Models/Requests/Request.cs b/Persistence/Models/Requests/PaginationRequest.cs similarity index 96% rename from Persistence/Models/Requests/Request.cs rename to Persistence/Models/Requests/PaginationRequest.cs index 30dd38a..d9974cd 100644 --- a/Persistence/Models/Requests/Request.cs +++ b/Persistence/Models/Requests/PaginationRequest.cs @@ -4,7 +4,7 @@ /// Контейнер для поддержки постраничного просмотра таблиц /// /// -public class Request +public class PaginationRequest { /// /// Кол-во записей пропущенных с начала таблицы в запросе от api diff --git a/Persistence/Models/Requests/SectionPartRequest.cs b/Persistence/Models/Requests/SectionPartRequest.cs index a05082d..3eca015 100644 --- a/Persistence/Models/Requests/SectionPartRequest.cs +++ b/Persistence/Models/Requests/SectionPartRequest.cs @@ -3,7 +3,7 @@ /// /// Запрос для фильтрации данных по секции и глубине /// -public class SectionPartRequest : Request +public class SectionPartRequest { /// /// Глубина забоя на дату начала интервала diff --git a/Persistence/Repositories/AbstractChangeLogRepository.cs b/Persistence/Repositories/AbstractChangeLogRepository.cs deleted file mode 100644 index 88cf511..0000000 --- a/Persistence/Repositories/AbstractChangeLogRepository.cs +++ /dev/null @@ -1,165 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Persistence.Models; -using System.Linq; - -namespace Persistence.Repositories; -//public abstract class AbstractChangeLogRepository : IChangeLogRepository -// where TDto : class, new() -// where TEntity : class, IChangeLogAbstract -// where TChangeLogDto : ChangeLogDto -//{ -// private readonly DbContext dbContext; - -// protected AbstractChangeLogRepository(DbContext dbContext) -// { -// this.dbContext = dbContext; -// } - -// public abstract TEntity Convert(TDto entity); -// public async Task Clear(int idUser,CancellationToken token) -// { -// throw new NotImplementedException(); - -// //var updateTime = DateTimeOffset.UtcNow; - -// ////todo -// //var query = BuildQuery(request); -// //query = query.Where(e => e.Obsolete == null); - -// //var entitiesToDelete = await query.ToArrayAsync(token); - -// //foreach (var entity in entitiesToDelete) -// //{ -// // entity.IdState = IChangeLogAbstract.IdCleared; -// // entity.Obsolete = updateTime; -// // entity.IdEditor = idUser; -// //} - -// //var result = await SaveChangesWithExceptionHandling(token); -// //return result; -// } - -// public async Task ClearAndInsertRange(int idUser, IEnumerable dtos, CancellationToken token) -// { -// var result = 0; -// using var transaction = await dbContext.Database.BeginTransactionAsync(token); -// try -// { -// result += await Clear(idUser, token); -// result += await InsertRangeWithoutTransaction(idUser, dtos, token); - -// await transaction.CommitAsync(token); -// return result; -// } -// catch -// { -// await transaction.RollbackAsync(token); -// throw; -// } -// } - -// public Task> GetCurrent(DateTimeOffset moment, CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// public Task> GetDatesChange(CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// public Task> GetGtDate(DateTimeOffset date, CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// public async Task InsertRange(int idUser, IEnumerable dtos, CancellationToken token) -// { -// using var transaction = dbContext.Database.BeginTransaction(); -// try -// { -// var result = await InsertRangeWithoutTransaction(idUser, dtos, token); -// await transaction.CommitAsync(token); -// return result; -// } -// catch -// { -// await transaction.RollbackAsync(token); -// throw; -// } -// } - -// protected abstract DatabaseFacade GetDataBase(); - -// public Task MarkAsDeleted(int idUser, IEnumerable ids, CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// public Task UpdateOrInsertRange(int idUser, IEnumerable dtos, CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// public Task UpdateRange(int idUser, IEnumerable dtos, CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// public Task> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token) -// { -// throw new NotImplementedException(); -// } - -// private async Task InsertRangeWithoutTransaction(int idUser, IEnumerable dtos, CancellationToken token) -// { -// var result = 0; -// if (dtos.Any()) -// { -// var entities = dtos.Select(Convert); -// var creation = DateTimeOffset.UtcNow; -// var dbSet = dbContext.Set(); -// foreach (var entity in entities) -// { -// entity.Id = default; -// entity.IdAuthor = idUser; -// entity.Creation = creation; -// entity.IdState = IChangeLogAbstract.IdStateActual; -// entity.IdEditor = null; -// entity.IdPrevious = null; -// entity.Obsolete = null; -// dbSet.Add(entity); -// } - -// result += await SaveChangesWithExceptionHandling(token); -// } - -// return result; -// } - -// private async Task SaveChangesWithExceptionHandling(CancellationToken token) -// { -// var result = await dbContext.SaveChangesAsync(token); -// return result; -// //try -// //{ -// // var result = await dbContext.SaveChangesAsync(token); -// // return result; -// //} -// //catch (DbUpdateException ex) -// //{ -// // if (ex.InnerException is PostgresException pgException) -// // TryConvertPostgresExceptionToValidateException(pgException); -// // throw; -// //} -// } - - - -// //private static void TryConvertPostgresExceptionToValidateException(PostgresException pgException) -// //{ -// // if (pgException.SqlState == PostgresErrorCodes.ForeignKeyViolation) -// // throw new ArgumentInvalidException("dtos", pgException.Message + "\r\n" + pgException.Detail); -// //} -//} diff --git a/Persistence/Repositories/IChangeLogRepository.cs b/Persistence/Repositories/IChangeLogRepository.cs index 2d668cc..e197090 100644 --- a/Persistence/Repositories/IChangeLogRepository.cs +++ b/Persistence/Repositories/IChangeLogRepository.cs @@ -12,60 +12,60 @@ public interface IChangeLogRepository : ISyncWithDiscriminatorRepository /// Добавление записей /// - /// пользователь, который добавляет + /// пользователь, который добавляет /// ключ справочника /// /// /// - Task InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Пометить записи как удаленные /// - /// + /// /// ключи записей /// /// - Task MarkAsDeleted(Guid idUser, IEnumerable ids, CancellationToken token); + Task MarkAsDeleted(Guid idEditor, IEnumerable ids, CancellationToken token); /// /// Пометить записи как удаленные /// - /// + /// /// дискриминатор таблицы /// /// - Task MarkAsDeleted(Guid idUser, Guid idDiscriminator, CancellationToken token); + Task MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token); /// /// Очистить и добавить новые /// - /// + /// /// /// /// /// - Task ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Редактирование записей /// - /// пользователь, который редактирует - /// + /// пользователь, который редактирует /// /// /// - Task UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token); /// /// Получение актуальных записей на определенный момент времени (с пагинацией) /// /// /// текущий момент времени - /// параметры запроса + /// параметры запроса фильтрации + /// параметры запроса пагинации /// /// - Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); + Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение измененных записей за период времени diff --git a/Persistence/Repositories/ITableDataRepository.cs b/Persistence/Repositories/ITableDataRepository.cs index 574ff76..0ca1715 100644 --- a/Persistence/Repositories/ITableDataRepository.cs +++ b/Persistence/Repositories/ITableDataRepository.cs @@ -7,7 +7,7 @@ namespace Persistence.Repositories; /// public interface ITableDataRepository where TDto : class, new() - where TRequest : Request + where TRequest : PaginationRequest { /// /// Получить страницу списка объектов -- 2.45.2 From ae3e164df17aaf5564c30e3105c21c26de7990ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Thu, 5 Dec 2024 11:30:07 +0500 Subject: [PATCH 15/23] Merge from dev --- .../Controllers/TechMessagesController.cs | 3 +- Persistence.API/DependencyInjection.cs | 24 ++--- .../Clients/ITechMessagesClient.cs | 3 +- .../PersistenceDbContext.cs | 19 ++-- .../Controllers/TechMessagesControllerTest.cs | 13 +-- .../Repositories/TechMessagesRepository.cs | 3 +- .../Repositories/ITechMessagesRepository.cs | 100 +++++++++--------- 7 files changed, 83 insertions(+), 82 deletions(-) diff --git a/Persistence.API/Controllers/TechMessagesController.cs b/Persistence.API/Controllers/TechMessagesController.cs index d2691c1..a7b0094 100644 --- a/Persistence.API/Controllers/TechMessagesController.cs +++ b/Persistence.API/Controllers/TechMessagesController.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Persistence.Models; +using Persistence.Models.Requests; using Persistence.Repositories; namespace Persistence.API.Controllers; @@ -36,7 +37,7 @@ public class TechMessagesController : ControllerBase /// /// [HttpGet] - public async Task>> GetPage([FromQuery] RequestDto request, CancellationToken token) + public async Task>> GetPage([FromQuery] PaginationRequest request, CancellationToken token) { var result = await techMessagesRepository.GetPage(request, token); diff --git a/Persistence.API/DependencyInjection.cs b/Persistence.API/DependencyInjection.cs index 6170eeb..bf297a6 100644 --- a/Persistence.API/DependencyInjection.cs +++ b/Persistence.API/DependencyInjection.cs @@ -1,4 +1,3 @@ -using System.Text.Json.Nodes; using Mapster; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; @@ -8,18 +7,19 @@ using Persistence.Database.Entity; using Persistence.Models; using Persistence.Models.Configurations; using Swashbuckle.AspNetCore.SwaggerGen; +using System.Reflection; using System.Text.Json.Nodes; namespace Persistence.API; public static class DependencyInjection { - public static void MapsterSetup() - { - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dest => dest.System, dest => dest.SystemId); - } + public static void MapsterSetup() + { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dest => dest.System, dest => dest.SystemId); + } public static void AddSwagger(this IServiceCollection services, IConfiguration configuration) { services.AddSwaggerGen(c => @@ -48,11 +48,11 @@ public static class DependencyInjection c.AddKeycloackSecurity(configuration); else c.AddDefaultSecurity(configuration); - var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - var includeControllerXmlComment = true; - c.IncludeXmlComments(xmlPath, includeControllerXmlComment); - }); + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + var includeControllerXmlComment = true; + c.IncludeXmlComments(xmlPath, includeControllerXmlComment); + }); } #region Authentication diff --git a/Persistence.Client/Clients/ITechMessagesClient.cs b/Persistence.Client/Clients/ITechMessagesClient.cs index 878c6cf..a9c80c1 100644 --- a/Persistence.Client/Clients/ITechMessagesClient.cs +++ b/Persistence.Client/Clients/ITechMessagesClient.cs @@ -1,4 +1,5 @@ using Persistence.Models; +using Persistence.Models.Requests; using Refit; namespace Persistence.Client.Clients @@ -11,7 +12,7 @@ namespace Persistence.Client.Clients private const string BaseRoute = "/api/techMessages"; [Get($"{BaseRoute}")] - Task>> GetPage([Query] RequestDto request, CancellationToken token); + Task>> GetPage([Query] PaginationRequest request, CancellationToken token); [Post($"{BaseRoute}")] Task> AddRange([Body] IEnumerable dtos, CancellationToken token); diff --git a/Persistence.Database.Postgres/PersistenceDbContext.cs b/Persistence.Database.Postgres/PersistenceDbContext.cs index 9d6e4cf..80a9e25 100644 --- a/Persistence.Database.Postgres/PersistenceDbContext.cs +++ b/Persistence.Database.Postgres/PersistenceDbContext.cs @@ -1,7 +1,5 @@ using Microsoft.EntityFrameworkCore; -using Npgsql; using Persistence.Database.Entity; -using System.Data.Common; namespace Persistence.Database.Model; public partial class PersistenceDbContext : DbContext @@ -9,16 +7,16 @@ public partial class PersistenceDbContext : DbContext public DbSet DataSaub => Set(); public DbSet ChangeLog => Set(); - public DbSet Setpoint => Set(); + public DbSet Setpoint => Set(); - public DbSet TechMessage => Set(); + public DbSet TechMessage => Set(); - public DbSet TimestampedSets => Set(); + public DbSet TimestampedSets => Set(); public PersistenceDbContext() : base() { - + } public PersistenceDbContext(DbContextOptions options) @@ -50,12 +48,11 @@ public partial class PersistenceDbContext : DbContext .WithMany() .HasForeignKey(t => t.SystemId) .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - } + .IsRequired(); + }); modelBuilder.Entity() - .Property(e => e.Value) - .HasJsonConversion(); + .Property(e => e.Value) + .HasJsonConversion(); } } diff --git a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs index 1f194ad..291991f 100644 --- a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs @@ -5,6 +5,7 @@ using Persistence.Client; using Persistence.Client.Clients; using Persistence.Database.Entity; using Persistence.Models; +using Persistence.Models.Requests; using Xunit; namespace Persistence.IntegrationTests.Controllers @@ -32,7 +33,7 @@ namespace Persistence.IntegrationTests.Controllers dbContext.CleanupDbSet(); dbContext.CleanupDbSet(); - var requestDto = new RequestDto() + var PaginationRequest = new PaginationRequest() { Skip = 1, Take = 2, @@ -40,14 +41,14 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await techMessagesClient.GetPage(requestDto, new CancellationToken()); + var response = await techMessagesClient.GetPage(PaginationRequest, new CancellationToken()); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response.Content); Assert.Empty(response.Content.Items); - Assert.Equal(requestDto.Skip, response.Content.Skip); - Assert.Equal(requestDto.Take, response.Content.Take); + Assert.Equal(PaginationRequest.Skip, response.Content.Skip); + Assert.Equal(PaginationRequest.Take, response.Content.Take); } [Fact] @@ -56,7 +57,7 @@ namespace Persistence.IntegrationTests.Controllers //arrange var dtos = await InsertRange(); var dtosCount = dtos.Count(); - var requestDto = new RequestDto() + var PaginationRequest = new PaginationRequest() { Skip = 0, Take = 2, @@ -64,7 +65,7 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await techMessagesClient.GetPage(requestDto, new CancellationToken()); + var response = await techMessagesClient.GetPage(PaginationRequest, new CancellationToken()); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); diff --git a/Persistence.Repository/Repositories/TechMessagesRepository.cs b/Persistence.Repository/Repositories/TechMessagesRepository.cs index c838619..d2efbe4 100644 --- a/Persistence.Repository/Repositories/TechMessagesRepository.cs +++ b/Persistence.Repository/Repositories/TechMessagesRepository.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Persistence.Database.Entity; using Persistence.Models; +using Persistence.Models.Requests; using Persistence.Repositories; using Persistence.Repository.Extensions; @@ -24,7 +25,7 @@ namespace Persistence.Repository.Repositories protected virtual IQueryable GetQueryReadOnly() => db.Set() .Include(e => e.System); - public async Task> GetPage(RequestDto request, CancellationToken token) + public async Task> GetPage(PaginationRequest request, CancellationToken token) { var query = GetQueryReadOnly(); var count = await query.CountAsync(token); diff --git a/Persistence/Repositories/ITechMessagesRepository.cs b/Persistence/Repositories/ITechMessagesRepository.cs index 92e8f70..ae92912 100644 --- a/Persistence/Repositories/ITechMessagesRepository.cs +++ b/Persistence/Repositories/ITechMessagesRepository.cs @@ -1,59 +1,59 @@ -using System.Threading.Tasks; -using Persistence.Models; +using Persistence.Models; +using Persistence.Models.Requests; namespace Persistence.Repositories { - /// - /// Интерфейс по работе с технологическими сообщениями - /// - public interface ITechMessagesRepository - { - /// - /// Получить страницу списка объектов - /// - /// - /// - /// - Task> GetPage(RequestDto request, CancellationToken token); + /// + /// Интерфейс по работе с технологическими сообщениями + /// + public interface ITechMessagesRepository + { + /// + /// Получить страницу списка объектов + /// + /// + /// + /// + Task> GetPage(PaginationRequest request, CancellationToken token); - /// - /// Добавление новых сообщений - /// - /// - /// - /// - Task AddRange(IEnumerable dtos, Guid userId, CancellationToken token); + /// + /// Добавление новых сообщений + /// + /// + /// + /// + Task AddRange(IEnumerable dtos, Guid userId, CancellationToken token); - /// - /// Получение списка уникальных названий систем АБ - /// - /// - /// - Task> GetSystems(CancellationToken token); + /// + /// Получение списка уникальных названий систем АБ + /// + /// + /// + Task> GetSystems(CancellationToken token); - /// - /// Получение количества сообщений по категориям и системам автобурения - /// - /// Id Категории важности - /// Система автобурения - /// - /// - Task> GetStatistics(IEnumerable autoDrillingSystem, IEnumerable categoryIds, CancellationToken token); + /// + /// Получение количества сообщений по категориям и системам автобурения + /// + /// Id Категории важности + /// Система автобурения + /// + /// + Task> GetStatistics(IEnumerable autoDrillingSystem, IEnumerable categoryIds, CancellationToken token); - /// - /// Получить порцию записей, начиная с заданной даты - /// - /// - /// - /// - /// - Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); + /// + /// Получить порцию записей, начиная с заданной даты + /// + /// + /// + /// + /// + Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token); - /// - /// Получить диапазон дат, для которых есть данные в репозитории - /// - /// - /// - Task GetDatesRangeAsync(CancellationToken token); - } + /// + /// Получить диапазон дат, для которых есть данные в репозитории + /// + /// + /// + Task GetDatesRangeAsync(CancellationToken token); + } } -- 2.45.2 From be2f9327960021edcf4394f4d946c71b7705de34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Thu, 5 Dec 2024 12:20:37 +0500 Subject: [PATCH 16/23] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=20=D0=BF?= =?UTF-8?q?=D1=83=D1=81=D1=82=D0=BE=D0=B9=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82?= =?UTF-8?q?=D1=80=D1=83=D0=BA=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Persistence/Models/ChangeLogDto.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Persistence/Models/ChangeLogDto.cs b/Persistence/Models/ChangeLogDto.cs index ba3ff5c..d42d659 100644 --- a/Persistence/Models/ChangeLogDto.cs +++ b/Persistence/Models/ChangeLogDto.cs @@ -5,11 +5,6 @@ namespace Persistence.Models; /// public class ChangeLogDto { - public ChangeLogDto() - { - - } - /// /// Ключ записи /// -- 2.45.2 From 231e14a4f6d0518da731edd78f4833947d99c492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Thu, 5 Dec 2024 18:13:52 +0500 Subject: [PATCH 17/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D1=82=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20(=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B8=D1=87=D0=BD=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 51 ++++++++--------- Persistence.Database/Entity/ChangeLog.cs | 56 ++++--------------- .../Entity/ITimestampedData.cs | 8 +-- .../Controllers/ChangeLogControllerTest.cs | 19 ++++++- .../Persistence.Repository.csproj | 1 + .../Repositories/ChangeLogRepository.cs | 50 ++++++++++------- 6 files changed, 88 insertions(+), 97 deletions(-) diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 233af58..54a3b0c 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -19,10 +19,10 @@ public class ChangeLogController : ControllerBase, IChangeLogApi this.repository = repository; } - [HttpPost] - [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + [HttpPost("{idDiscriminator}")] + [ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)] public async Task Add( - Guid idDiscriminator, + [FromRoute] Guid idDiscriminator, [FromBody] DataWithWellDepthAndSectionDto dto, CancellationToken token) { @@ -32,11 +32,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return CreatedAtAction(nameof(Add), result); } - [HttpPost("range")] - [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] + [HttpPost("range/{idDiscriminator}")] + [ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)] public async Task AddRange( - Guid idDiscriminator, - [FromBody] IEnumerable dtos, + [FromRoute] Guid idDiscriminator, + [FromBody] IEnumerable dtos, CancellationToken token = default) { var userId = User.GetUserId(); @@ -65,11 +65,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } - [HttpPost("replace")] + [HttpPost("replace/{idDiscriminator}")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task ClearAndAddRange( - Guid idDiscriminator, - IEnumerable dtos, + [FromRoute] Guid idDiscriminator, + [FromBody] IEnumerable dtos, CancellationToken token = default) { var userId = User.GetUserId(); @@ -101,11 +101,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } - [HttpGet] + [HttpGet("{idDiscriminator}")] [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetCurrent( - Guid idDiscriminator, - [FromQuery]SectionPartRequest filterRequest, + [FromRoute] Guid idDiscriminator, + [FromQuery] SectionPartRequest filterRequest, [FromQuery] PaginationRequest paginationRequest, CancellationToken token = default) { @@ -115,10 +115,10 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } - [HttpGet("moment")] + [HttpGet("moment/{idDiscriminator}")] [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetByDate( - Guid idDiscriminator, + [FromRoute] Guid idDiscriminator, DateTimeOffset moment, [FromQuery] SectionPartRequest filterRequest, [FromQuery] PaginationRequest paginationRequest, @@ -129,11 +129,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } - [HttpGet("history")] + [HttpGet("history/{idDiscriminator}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] public async Task GetChangeLogForDate( - Guid idDiscriminator, - DateTimeOffset dateBegin, + [FromRoute] Guid idDiscriminator, + DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token = default) { @@ -142,31 +142,32 @@ public class ChangeLogController : ControllerBase, IChangeLogApi return Ok(result); } - [HttpGet("datesChange")] + [HttpGet("datesChange/{idDiscriminator}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task GetDatesChange(Guid idDiscriminator, CancellationToken token = default) + public async Task GetDatesChange([FromRoute] Guid idDiscriminator, CancellationToken token = default) { var result = await repository.GetDatesChange(idDiscriminator, token); return Ok(result); } - [HttpGet("part")] + [HttpGet("part/{idDiscriminator}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task GetPart(Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default) + public async Task GetPart([FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default) { var result = await repository.GetGtDate(idDiscriminator, dateBegin, token); return Ok(result); } - [HttpGet("datesRange")] + [HttpGet("datesRange/{idDiscriminator}")] [ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)] - public async Task GetDatesRangeAsync(Guid idDiscriminator, CancellationToken token = default) + [ProducesResponseType((int)HttpStatusCode.NoContent)] + public async Task GetDatesRangeAsync([FromRoute] Guid idDiscriminator, CancellationToken token = default) { var result = await repository.GetDatesRange(idDiscriminator, token); - if(result is null) + if (result is null) return NoContent(); return Ok(result); diff --git a/Persistence.Database/Entity/ChangeLog.cs b/Persistence.Database/Entity/ChangeLog.cs index 7100fc1..2585ace 100644 --- a/Persistence.Database/Entity/ChangeLog.cs +++ b/Persistence.Database/Entity/ChangeLog.cs @@ -1,6 +1,7 @@  using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; namespace Persistence.Database.Model; @@ -9,69 +10,36 @@ namespace Persistence.Database.Model; /// public class ChangeLog : IChangeLog { - /// - /// Ключ записи - /// - [Key, Column("Id")] + [Key, Comment("Ключ записи")] public Guid Id { get; set; } - /// - /// Дискриминатор таблицы - /// - [Column("IdDiscriminator")] + [Comment("Дискриминатор таблицы")] public Guid IdDiscriminator { get; set; } - /// - /// Автор изменения - /// - [Column("IdAuthor")] + [Comment("Автор изменения")] public Guid IdAuthor { get; set; } - /// - /// Редактор - /// - [Column("IdEditor")] + [Comment("Редактор")] public Guid? IdEditor { get; set; } - /// - /// Дата создания записи - /// - [Column("Creation")] + [Comment("Дата создания записи")] public DateTimeOffset Creation { get; set; } - /// - /// Дата устаревания (например при удалении) - /// - [Column("Obsolete")] + [Comment("Дата устаревания (например при удалении)")] public DateTimeOffset? Obsolete { get; set; } - /// - /// Id заменяющей записи - /// - [Column("IdNext")] + [Comment("Id заменяющей записи")] public Guid? IdNext { get; set; } - /// - /// Глубина забоя на дату начала интервала - /// - [Column("DepthStart")] + [Comment("Глубина забоя на дату начала интервала")] public double DepthStart { get; set; } - /// - /// Глубина забоя на дату окончания интервала - /// - [Column("DepthEnd")] + [Comment("Глубина забоя на дату окончания интервала")] public double DepthEnd { get; set; } - /// - /// Ключ секции - /// - [Column("IdSection")] + [Comment("Ключ секции")] public Guid IdSection { get; set; } - /// - /// Значение - /// - [Column("Value", TypeName = "jsonb")] + [Column(TypeName = "jsonb"), Comment("Значение")] public required IDictionary Value { get; set; } } diff --git a/Persistence.Database/Entity/ITimestampedData.cs b/Persistence.Database/Entity/ITimestampedData.cs index 9241ca5..ce21da5 100644 --- a/Persistence.Database/Entity/ITimestampedData.cs +++ b/Persistence.Database/Entity/ITimestampedData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Persistence.Database.Model; +namespace Persistence.Database.Model; public interface ITimestampedData { /// diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index 0f24bb8..8fc572a 100644 --- a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -24,7 +24,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest } [Fact] - public async Task ClearAndInsertRange() + public async Task ClearAndInsertRange_InEmptyDb() { // arrange var idDiscriminator = Guid.NewGuid(); @@ -38,6 +38,23 @@ public class ChangeLogControllerTest : BaseIntegrationTest Assert.Equal(2, result.Content); } + [Fact] + public async Task ClearAndInsertRange_InNotEmptyDb() + { + // arrange + var insertedCount = 10; + var createdResult = CreateChangeLogItems(insertedCount, (-15, 15)); + var idDiscriminator = createdResult.Item1; + var dtos = createdResult.Item2.Select(e => e.Adapt()); + + // act + var result = await client.ClearAndAddRange(idDiscriminator, dtos); + + // assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Equal(insertedCount*2, result.Content); + } + [Fact] public async Task Add_returns_success() { diff --git a/Persistence.Repository/Persistence.Repository.csproj b/Persistence.Repository/Persistence.Repository.csproj index 55bd8ea..833fc6f 100644 --- a/Persistence.Repository/Persistence.Repository.csproj +++ b/Persistence.Repository/Persistence.Repository.csproj @@ -8,6 +8,7 @@ + diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 07159d7..16790a7 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -4,6 +4,7 @@ using Persistence.Database.Model; using Persistence.Models; using Persistence.Models.Requests; using Persistence.Repositories; +using UuidExtensions; namespace Persistence.Repository.Repositories; public class ChangeLogRepository : IChangeLogRepository @@ -17,11 +18,13 @@ public class ChangeLogRepository : IChangeLogRepository public async Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { + var entities = new List(); foreach (var dto in dtos) { var entity = CreateEntityFromDto(idAuthor, idDiscriminator, dto); - db.Set().Add(entity); + entities.Add(entity); } + db.Set().AddRange(entities); var result = await db.SaveChangesAsync(token); @@ -30,10 +33,18 @@ public class ChangeLogRepository : IChangeLogRepository public async Task MarkAsDeleted(Guid idEditor, IEnumerable ids, CancellationToken token) { - var query = db.Set().Where(s => ids.Contains(s.Id)); + var query = db.Set() + .Where(s => ids.Contains(s.Id)) + .Where(s => s.Obsolete != null); + + if(query.Count() != ids.Count()) + { + throw new ArgumentException("Count of active items not equal count of ids", nameof(ids)); + } + var entities = await query.ToArrayAsync(token); - var result = await Clear(idEditor, entities, token); + var result = await MarkAsObsolete(idEditor, entities, token); return result; } @@ -43,14 +54,15 @@ public class ChangeLogRepository : IChangeLogRepository var query = db.Set() .Where(s => s.IdDiscriminator == idDiscriminator) .Where(e => e.Obsolete == null); + var entities = await query.ToArrayAsync(token); - var result = await Clear(idEditor, entities, token); + var result = await MarkAsObsolete(idEditor, entities, token); return result; } - private async Task Clear(Guid idEditor, IEnumerable entities, CancellationToken token) + private async Task MarkAsObsolete(Guid idEditor, IEnumerable entities, CancellationToken token) { var updateTime = DateTimeOffset.UtcNow; @@ -66,20 +78,16 @@ public class ChangeLogRepository : IChangeLogRepository public async Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var result = 0; - using var transaction = await db.Database.BeginTransactionAsync(token); - try - { - result += await MarkAsDeleted(idAuthor, idDiscriminator, token); - result += await AddRange(idAuthor, idDiscriminator, dtos, token); - await transaction.CommitAsync(token); - return result; - } - catch - { - await transaction.RollbackAsync(token); - throw; - } + using var transaction = await db.Database.BeginTransactionAsync(token); + + result += await MarkAsDeleted(idAuthor, idDiscriminator, token); + result += await AddRange(idAuthor, idDiscriminator, dtos, token); + + await transaction.CommitAsync(token); + + + return result; } public async Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token) @@ -100,7 +108,7 @@ public class ChangeLogRepository : IChangeLogRepository var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id); if(updatedEntity is null) { - throw new ArgumentNullException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); + throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); } var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto); @@ -131,6 +139,7 @@ public class ChangeLogRepository : IChangeLogRepository CancellationToken token) { var query = BuildQuery(idDiscriminator, momentUtc, filterRequest); + //ApplyFilter(query, , filterRequest); var result = await BuildPaginationContainer(query, paginationRequest, token); return result; @@ -138,6 +147,7 @@ public class ChangeLogRepository : IChangeLogRepository private IQueryable BuildQuery(Guid idDiscriminator, DateTimeOffset momentUtc, SectionPartRequest request) { + momentUtc = momentUtc.ToUniversalTime(); var query = db.Set() .Where(e => e.IdDiscriminator == idDiscriminator) .Where(e => e.Creation <= momentUtc) @@ -242,7 +252,7 @@ public class ChangeLogRepository : IChangeLogRepository { var entity = new ChangeLog() { - Id = default, + Id = Uuid7.Guid(), Creation = DateTimeOffset.UtcNow, IdAuthor = idAuthor, IdDiscriminator = idDiscriminator, -- 2.45.2 From 2e567e7eba738104adefc1dd5dd98bc59266d02f Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 6 Dec 2024 14:55:07 +0500 Subject: [PATCH 18/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20(=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=87=D0=B0=D0=BD=D0=B8=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Persistence.Database/Entity/ChangeLog.cs | 3 +- Persistence.Database/Entity/IChangeLog.cs | 2 - .../Persistence.Database.csproj | 4 + Persistence.Repository/QueryBuilders.cs | 76 +++++++++++++++++ .../Repositories/ChangeLogRepository.cs | 82 ++++--------------- Persistence/Models/IWithSectionPart.cs | 9 ++ 6 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 Persistence.Repository/QueryBuilders.cs create mode 100644 Persistence/Models/IWithSectionPart.cs diff --git a/Persistence.Database/Entity/ChangeLog.cs b/Persistence.Database/Entity/ChangeLog.cs index 2585ace..9a8001b 100644 --- a/Persistence.Database/Entity/ChangeLog.cs +++ b/Persistence.Database/Entity/ChangeLog.cs @@ -2,13 +2,14 @@ using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations; using Microsoft.EntityFrameworkCore; +using Persistence.Models; namespace Persistence.Database.Model; /// /// Часть записи, описывающая изменение /// -public class ChangeLog : IChangeLog +public class ChangeLog : IChangeLog, IWithSectionPart { [Key, Comment("Ключ записи")] public Guid Id { get; set; } diff --git a/Persistence.Database/Entity/IChangeLog.cs b/Persistence.Database/Entity/IChangeLog.cs index 04e08a4..c4dc962 100644 --- a/Persistence.Database/Entity/IChangeLog.cs +++ b/Persistence.Database/Entity/IChangeLog.cs @@ -1,6 +1,4 @@  -using System.ComponentModel.DataAnnotations.Schema; - namespace Persistence.Database.Model; /// diff --git a/Persistence.Database/Persistence.Database.csproj b/Persistence.Database/Persistence.Database.csproj index 8154daf..3019e82 100644 --- a/Persistence.Database/Persistence.Database.csproj +++ b/Persistence.Database/Persistence.Database.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/Persistence.Repository/QueryBuilders.cs b/Persistence.Repository/QueryBuilders.cs new file mode 100644 index 0000000..23f5462 --- /dev/null +++ b/Persistence.Repository/QueryBuilders.cs @@ -0,0 +1,76 @@ +using Microsoft.EntityFrameworkCore; +using Persistence.Database.Model; +using Persistence.Models; +using Persistence.Models.Requests; + +namespace Persistence.Repository; + +/// +/// класс с набором методов, необходимых для фильтрации записей +/// +public static class QueryBuilders +{ + public static void Apply(this IQueryable query, SectionPartRequest request) + where TEntity : class, IWithSectionPart + { + if (request.IdSection.HasValue) + { + query = query.Where(e => e.IdSection == request.IdSection); + } + if (request.DepthStart.HasValue) + { + query = query.Where(e => e.DepthStart >= request.DepthStart); + } + if (request.DepthEnd.HasValue) + { + query = query.Where(e => e.DepthEnd <= request.DepthEnd); + } + } + + public static void Apply(this IQueryable query,DateTimeOffset momentUtc) + where TEntity : class, IChangeLog + { + momentUtc = momentUtc.ToUniversalTime(); + + query = query + .Where(e => e.Creation <= momentUtc) + .Where(e => e.Obsolete == null || e.Obsolete >= momentUtc); + } + + + public static async Task> ApplyPagination( + this IQueryable query, + PaginationRequest request, + Func Convert, + CancellationToken token) + where TEntity : class, IWithSectionPart + where TDto : class + { + if (String.IsNullOrEmpty(request.SortSettings)) + { + query = query + .OrderBy(e => e.IdSection) + .ThenBy(e => e.DepthStart) + .ThenBy(e => e.DepthEnd); + } + else + { + query = query.SortBy(request.SortSettings); + } + + var entities = await query + .Skip(request.Skip) + .Take(request.Take) + .ToArrayAsync(token); + + var result = new PaginationContainer + { + Skip = request.Skip, + Take = request.Take, + Items = entities.Select(Convert), + Count = await query.CountAsync(token) + }; + + return result; + } +} diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 16790a7..7f6d573 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -37,7 +37,7 @@ public class ChangeLogRepository : IChangeLogRepository .Where(s => ids.Contains(s.Id)) .Where(s => s.Obsolete != null); - if(query.Count() != ids.Count()) + if (query.Count() != ids.Count()) { throw new ArgumentException("Count of active items not equal count of ids", nameof(ids)); } @@ -80,13 +80,13 @@ public class ChangeLogRepository : IChangeLogRepository var result = 0; using var transaction = await db.Database.BeginTransactionAsync(token); - + result += await MarkAsDeleted(idAuthor, idDiscriminator, token); result += await AddRange(idAuthor, idDiscriminator, dtos, token); await transaction.CommitAsync(token); - + return result; } @@ -106,7 +106,7 @@ public class ChangeLogRepository : IChangeLogRepository foreach (var dto in dtos) { var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id); - if(updatedEntity is null) + if (updatedEntity is null) { throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); } @@ -138,33 +138,18 @@ public class ChangeLogRepository : IChangeLogRepository PaginationRequest paginationRequest, CancellationToken token) { - var query = BuildQuery(idDiscriminator, momentUtc, filterRequest); - //ApplyFilter(query, , filterRequest); - var result = await BuildPaginationContainer(query, paginationRequest, token); + var query = CreateQuery(idDiscriminator); + query.Apply(momentUtc); + query.Apply(filterRequest); + + var result = await query.ApplyPagination(paginationRequest, Convert, token); return result; } - private IQueryable BuildQuery(Guid idDiscriminator, DateTimeOffset momentUtc, SectionPartRequest request) + private IQueryable CreateQuery(Guid idDiscriminator) { - momentUtc = momentUtc.ToUniversalTime(); - var query = db.Set() - .Where(e => e.IdDiscriminator == idDiscriminator) - .Where(e => e.Creation <= momentUtc) - .Where(e => e.Obsolete == null || e.Obsolete >= momentUtc); - - if (request.IdSection.HasValue) - { - query = query.Where(e => e.IdSection == request.IdSection); - } - if (request.DepthStart.HasValue) - { - query = query.Where(e => e.DepthStart >= request.DepthStart); - } - if (request.DepthEnd.HasValue) - { - query = query.Where(e => e.DepthEnd <= request.DepthEnd); - } + var query = db.Set().Where(e => e.IdDiscriminator == idDiscriminator); return query; } @@ -173,8 +158,8 @@ public class ChangeLogRepository : IChangeLogRepository { var query = db.Set().Where(s => s.IdDiscriminator == idDiscriminator); - var min = new DateTimeOffset(dateBegin.Year, dateBegin.Month, dateBegin.Day, 0, 0, 0, TimeSpan.Zero); - var max = new DateTimeOffset(dateEnd.Year, dateEnd.Month, dateEnd.Day, 0, 0, 0, TimeSpan.Zero); + var min = new DateTimeOffset(dateBegin.ToUniversalTime().Date, TimeSpan.Zero); + var max = new DateTimeOffset(dateEnd.ToUniversalTime().Date, TimeSpan.Zero); var createdQuery = query.Where(e => e.Creation >= min && e.Creation <= max); var editedQuery = query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max); @@ -189,39 +174,6 @@ public class ChangeLogRepository : IChangeLogRepository - private async Task> BuildPaginationContainer(IQueryable query, PaginationRequest request, CancellationToken token) - { - var result = new PaginationContainer - { - Skip = request.Skip, - Take = request.Take, - Items = Enumerable.Empty(), - Count = await query.CountAsync(token) - }; - - if (!String.IsNullOrEmpty(request.SortSettings)) - { - query = query.SortBy(request.SortSettings); - } - else - { - query = query - .OrderBy(e => e.IdSection) - .ThenBy(e => e.DepthStart) - .ThenBy(e => e.DepthEnd); - } - - var entities = await query - .Skip(result.Skip) - .Take(result.Take) - .ToArrayAsync(token); - - var dtos = entities.Select(e => e.Adapt()); - result.Items = dtos; - - return result; - } - public async Task> GetDatesChange(Guid idDiscriminator, CancellationToken token) { var query = db.Set().Where(e => e.IdDiscriminator == idDiscriminator); @@ -276,7 +228,7 @@ public class ChangeLogRepository : IChangeLogRepository var entities = await query.ToArrayAsync(token); - var dtos = entities.Select(e => e.Adapt()); + var dtos = entities.Select(Convert); return dtos; } @@ -289,12 +241,12 @@ public class ChangeLogRepository : IChangeLogRepository .Select(group => new { Min = group.Min(e => e.Creation), - Max = group.Max(e => e.Creation), + Max = group.Max(e => (e.Creation > e.Obsolete ? e.Creation : e.Obsolete!.Value)), }); var values = await query.FirstOrDefaultAsync(token); - if(values is null) + if (values is null) { return null; } @@ -305,4 +257,6 @@ public class ChangeLogRepository : IChangeLogRepository To = values.Max, }; } + + private DataWithWellDepthAndSectionDto Convert(ChangeLog entity) => entity.Adapt(); } diff --git a/Persistence/Models/IWithSectionPart.cs b/Persistence/Models/IWithSectionPart.cs new file mode 100644 index 0000000..adb5fdd --- /dev/null +++ b/Persistence/Models/IWithSectionPart.cs @@ -0,0 +1,9 @@ +namespace Persistence.Models; +public interface IWithSectionPart +{ + public double DepthStart { get; set; } + + public double DepthEnd { get; set; } + + public Guid IdSection { get; set; } +} -- 2.45.2 From 8d2a22a38f0be4f5911d9596090b035d20030ca3 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 6 Dec 2024 16:19:42 +0500 Subject: [PATCH 19/23] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20idDiscriminator=20=D0=B2=20=D1=80=D0=BE=D1=83?= =?UTF-8?q?=D1=82=20=D0=B4=D0=BB=D1=8F=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D1=85=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BE=D0=B2=20+=20=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB?= =?UTF-8?q?=D1=8C=D1=82=D0=B0=D1=82=D0=B0=D0=BC=20=D0=BF=D1=80=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=D0=BD=D0=B0=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Persistence.Client/Clients/IChangeLogClient.cs | 18 +++++++++--------- .../Repositories/ChangeLogRepository.cs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Persistence.Client/Clients/IChangeLogClient.cs b/Persistence.Client/Clients/IChangeLogClient.cs index 4f1cc60..dcbc9e2 100644 --- a/Persistence.Client/Clients/IChangeLogClient.cs +++ b/Persistence.Client/Clients/IChangeLogClient.cs @@ -17,7 +17,7 @@ public interface IChangeLogClient /// /// /// - [Post($"{BaseRoute}/replace")] + [Post($"{BaseRoute}/replace/{{idDiscriminator}}")] Task> ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos); /// @@ -28,10 +28,10 @@ public interface IChangeLogClient /// параметры запроса фильтрации /// параметры запроса пагинации /// - [Get($"{BaseRoute}/moment")] + [Get($"{BaseRoute}/moment/{{idDiscriminator}}")] Task>> GetByDate( - Guid idDiscriminator, - DateTimeOffset moment, + Guid idDiscriminator, + DateTimeOffset moment, [Query] SectionPartRequest filterRequest, [Query] PaginationRequest paginationRequest); @@ -42,7 +42,7 @@ public interface IChangeLogClient /// /// /// - [Get($"{BaseRoute}/history")] + [Get($"{BaseRoute}/history/{{idDiscriminator}}")] Task>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd); /// @@ -51,7 +51,7 @@ public interface IChangeLogClient /// /// /// - [Post($"{BaseRoute}")] + [Post($"{BaseRoute}/{{idDiscriminator}}")] Task> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto); /// @@ -60,7 +60,7 @@ public interface IChangeLogClient /// /// /// - [Post($"{BaseRoute}/range")] + [Post($"{BaseRoute}/range/{{idDiscriminator}}")] Task> AddRange(Guid idDiscriminator, IEnumerable dtos); /// @@ -69,7 +69,7 @@ public interface IChangeLogClient /// /// /// - [Put($"{BaseRoute}")] + [Put($"{BaseRoute}/{{idDiscriminator}}")] Task> Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto); /// @@ -78,7 +78,7 @@ public interface IChangeLogClient /// /// /// - [Put($"{BaseRoute}/range")] + [Put($"{BaseRoute}/range/{{idDiscriminator}}")] Task> UpdateRange(Guid idDiscriminator, IEnumerable dtos); /// diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 7f6d573..78c2eba 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -35,7 +35,7 @@ public class ChangeLogRepository : IChangeLogRepository { var query = db.Set() .Where(s => ids.Contains(s.Id)) - .Where(s => s.Obsolete != null); + .Where(s => s.Obsolete == null); if (query.Count() != ids.Count()) { -- 2.45.2 From e826a386d2c3890e9ece22f00e6ca3a198099420 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 6 Dec 2024 16:34:34 +0500 Subject: [PATCH 20/23] =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=BE?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Persistence.Client/Clients/IChangeLogClient.cs | 12 +++++------- .../Controllers/ChangeLogControllerTest.cs | 7 +++---- .../Repositories/ChangeLogRepository.cs | 4 +++- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Persistence.Client/Clients/IChangeLogClient.cs b/Persistence.Client/Clients/IChangeLogClient.cs index dcbc9e2..06bbc4d 100644 --- a/Persistence.Client/Clients/IChangeLogClient.cs +++ b/Persistence.Client/Clients/IChangeLogClient.cs @@ -66,20 +66,18 @@ public interface IChangeLogClient /// /// Обновить одну запись /// - /// /// /// - [Put($"{BaseRoute}/{{idDiscriminator}}")] - Task> Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto); + [Put($"{BaseRoute}")] + Task> Update(DataWithWellDepthAndSectionDto dto); /// /// Обновить несколько записей /// - /// /// /// - [Put($"{BaseRoute}/range/{{idDiscriminator}}")] - Task> UpdateRange(Guid idDiscriminator, IEnumerable dtos); + [Put($"{BaseRoute}/range")] + Task> UpdateRange(IEnumerable dtos); /// /// Удалить одну запись @@ -102,7 +100,7 @@ public interface IChangeLogClient /// /// /// - [Get($"{BaseRoute}/datesRange")] + [Get($"{BaseRoute}/datesRange/{{idDiscriminator}}")] Task> GetDatesRange(Guid idDiscriminator); } diff --git a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index 8fc572a..8c3b422 100644 --- a/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -105,7 +105,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest dto.DepthEnd = dto.DepthEnd + 10; // act - result = await client.Update(idDiscriminator, dto); + result = await client.Update(dto); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); @@ -143,7 +143,6 @@ public class ChangeLogControllerTest : BaseIntegrationTest { // arrange var count = 2; - var idDiscriminator = Guid.NewGuid(); var dtos = Generate(count, DateTimeOffset.UtcNow); var entities = dtos.Select(d => d.Adapt()).ToArray(); dbContext.ChangeLog.AddRange(entities); @@ -159,7 +158,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest }).ToArray(); // act - var result = await client.UpdateRange(idDiscriminator, dtos); + var result = await client.UpdateRange(dtos); // assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); @@ -298,7 +297,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest entity.DepthEnd = entity.DepthEnd + 10; } var dtos = entities.Select(e => e.Adapt()).ToArray(); - await client.UpdateRange(idDiscriminator, dtos); + await client.UpdateRange(dtos); //act var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter); diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 78c2eba..53eba23 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -241,7 +241,9 @@ public class ChangeLogRepository : IChangeLogRepository .Select(group => new { Min = group.Min(e => e.Creation), - Max = group.Max(e => (e.Creation > e.Obsolete ? e.Creation : e.Obsolete!.Value)), + Max = group.Max(e => (e.Obsolete.HasValue && e.Obsolete > e.Creation) + ? e.Obsolete.Value + : e.Creation), }); var values = await query.FirstOrDefaultAsync(token); -- 2.45.2 From f647afcd53056796c4211a15818e294ecc56ae1d Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Fri, 6 Dec 2024 17:06:16 +0500 Subject: [PATCH 21/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Persistence.Repository/QueryBuilders.cs | 8 ++++++-- .../Repositories/ChangeLogRepository.cs | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Persistence.Repository/QueryBuilders.cs b/Persistence.Repository/QueryBuilders.cs index 23f5462..9ed98e5 100644 --- a/Persistence.Repository/QueryBuilders.cs +++ b/Persistence.Repository/QueryBuilders.cs @@ -10,7 +10,7 @@ namespace Persistence.Repository; /// public static class QueryBuilders { - public static void Apply(this IQueryable query, SectionPartRequest request) + public static IQueryable Apply(this IQueryable query, SectionPartRequest request) where TEntity : class, IWithSectionPart { if (request.IdSection.HasValue) @@ -25,9 +25,11 @@ public static class QueryBuilders { query = query.Where(e => e.DepthEnd <= request.DepthEnd); } + + return query; } - public static void Apply(this IQueryable query,DateTimeOffset momentUtc) + public static IQueryable Apply(this IQueryable query,DateTimeOffset momentUtc) where TEntity : class, IChangeLog { momentUtc = momentUtc.ToUniversalTime(); @@ -35,6 +37,8 @@ public static class QueryBuilders query = query .Where(e => e.Creation <= momentUtc) .Where(e => e.Obsolete == null || e.Obsolete >= momentUtc); + + return query; } diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 53eba23..4b5d901 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -139,8 +139,8 @@ public class ChangeLogRepository : IChangeLogRepository CancellationToken token) { var query = CreateQuery(idDiscriminator); - query.Apply(momentUtc); - query.Apply(filterRequest); + query = query.Apply(momentUtc); + query = query.Apply(filterRequest); var result = await query.ApplyPagination(paginationRequest, Convert, token); -- 2.45.2 From 4ccbe4361a31fcbce596e7cc18b24a6c0ca23f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Mon, 9 Dec 2024 10:15:17 +0500 Subject: [PATCH 22/23] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 25 +++++++++++-------- Persistence.Repository/QueryBuilders.cs | 6 +++-- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Persistence.API/Controllers/ChangeLogController.cs b/Persistence.API/Controllers/ChangeLogController.cs index 54a3b0c..cad59c4 100644 --- a/Persistence.API/Controllers/ChangeLogController.cs +++ b/Persistence.API/Controllers/ChangeLogController.cs @@ -37,7 +37,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task AddRange( [FromRoute] Guid idDiscriminator, [FromBody] IEnumerable dtos, - CancellationToken token = default) + CancellationToken token) { var userId = User.GetUserId(); var result = await repository.AddRange(userId, idDiscriminator, dtos, token); @@ -47,7 +47,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpDelete] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] - public async Task Delete(Guid id, CancellationToken token = default) + public async Task Delete(Guid id, CancellationToken token) { var userId = User.GetUserId(); var result = await repository.MarkAsDeleted(userId, [id], token); @@ -57,7 +57,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpDelete("range")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] - public async Task DeleteRange(IEnumerable ids, CancellationToken token = default) + public async Task DeleteRange(IEnumerable ids, CancellationToken token) { var userId = User.GetUserId(); var result = await repository.MarkAsDeleted(userId, ids, token); @@ -70,7 +70,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi public async Task ClearAndAddRange( [FromRoute] Guid idDiscriminator, [FromBody] IEnumerable dtos, - CancellationToken token = default) + CancellationToken token) { var userId = User.GetUserId(); var result = await repository.ClearAndAddRange(userId, idDiscriminator, dtos, token); @@ -81,7 +81,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task Update( DataWithWellDepthAndSectionDto dto, - CancellationToken token = default) + CancellationToken token) { var userId = User.GetUserId(); var result = await repository.UpdateRange(userId, [dto], token); @@ -93,7 +93,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task UpdateRange( IEnumerable dtos, - CancellationToken token = default) + CancellationToken token) { var userId = User.GetUserId(); var result = await repository.UpdateRange(userId, dtos, token); @@ -107,7 +107,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [FromRoute] Guid idDiscriminator, [FromQuery] SectionPartRequest filterRequest, [FromQuery] PaginationRequest paginationRequest, - CancellationToken token = default) + CancellationToken token) { var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token); @@ -122,7 +122,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi DateTimeOffset moment, [FromQuery] SectionPartRequest filterRequest, [FromQuery] PaginationRequest paginationRequest, - CancellationToken token = default) + CancellationToken token) { var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token); @@ -131,11 +131,12 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("history/{idDiscriminator}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task GetChangeLogForDate( [FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, - CancellationToken token = default) + CancellationToken token) { var result = await repository.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, token); @@ -144,7 +145,8 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("datesChange/{idDiscriminator}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task GetDatesChange([FromRoute] Guid idDiscriminator, CancellationToken token = default) + [ProducesResponseType((int)HttpStatusCode.NoContent)] + public async Task GetDatesChange([FromRoute] Guid idDiscriminator, CancellationToken token) { var result = await repository.GetDatesChange(idDiscriminator, token); @@ -153,6 +155,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("part/{idDiscriminator}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task GetPart([FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default) { var result = await repository.GetGtDate(idDiscriminator, dateBegin, token); @@ -163,7 +166,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpGet("datesRange/{idDiscriminator}")] [ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] - public async Task GetDatesRangeAsync([FromRoute] Guid idDiscriminator, CancellationToken token = default) + public async Task GetDatesRangeAsync([FromRoute] Guid idDiscriminator, CancellationToken token) { var result = await repository.GetDatesRange(idDiscriminator, token); diff --git a/Persistence.Repository/QueryBuilders.cs b/Persistence.Repository/QueryBuilders.cs index 9ed98e5..6070a8a 100644 --- a/Persistence.Repository/QueryBuilders.cs +++ b/Persistence.Repository/QueryBuilders.cs @@ -67,12 +67,14 @@ public static class QueryBuilders .Take(request.Take) .ToArrayAsync(token); + var count = await query.CountAsync(token); + var items = entities.Select(Convert); var result = new PaginationContainer { Skip = request.Skip, Take = request.Take, - Items = entities.Select(Convert), - Count = await query.CountAsync(token) + Items = items, + Count = count }; return result; -- 2.45.2 From 42fe4dee5070dfc4d9931974f2d3390133111d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Mon, 9 Dec 2024 14:45:33 +0500 Subject: [PATCH 23/23] =?UTF-8?q?=D0=94=D0=BB=D1=8F=20=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8=D0=B8=20=D0=B1=D0=BB=D0=BE?= =?UTF-8?q?=D0=BA=20try-catch=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D0=BD=D1=83=D0=B6=D0=B5=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositories/ChangeLogRepository.cs | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/Persistence.Repository/Repositories/ChangeLogRepository.cs b/Persistence.Repository/Repositories/ChangeLogRepository.cs index 4b5d901..ac00e05 100644 --- a/Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -101,34 +101,29 @@ public class ChangeLogRepository : IChangeLogRepository var result = 0; using var transaction = await db.Database.BeginTransactionAsync(token); - try + + foreach (var dto in dtos) { - foreach (var dto in dtos) + var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id); + if (updatedEntity is null) { - var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id); - if (updatedEntity is null) - { - throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); - } - - var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto); - dbSet.Add(newEntity); - - updatedEntity.IdNext = newEntity.Id; - updatedEntity.Obsolete = DateTimeOffset.UtcNow; - updatedEntity.IdEditor = idEditor; + throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); } - result = await db.SaveChangesAsync(token); - await transaction.CommitAsync(token); + var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto); + dbSet.Add(newEntity); - return result; - } - catch - { - await transaction.RollbackAsync(token); - throw; + updatedEntity.IdNext = newEntity.Id; + updatedEntity.Obsolete = DateTimeOffset.UtcNow; + updatedEntity.IdEditor = idEditor; } + + result = await db.SaveChangesAsync(token); + await transaction.CommitAsync(token); + + return result; + + } public async Task> GetByDate( -- 2.45.2