From 719cd8139148312fc93d27869fd8f1f78a8dbbe7 Mon Sep 17 00:00:00 2001 From: "gorbenko.pavel" Date: Thu, 23 Jul 2026 12:50:31 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B2=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entities/TemplateRoute.cs | 2 +- .../Entities/TemplateRouteStep.cs | 3 +- .../Enums/HeadType.cs | 8 ++++ .../Enums/RouteStepStatus.cs | 9 +--- .../Persistence/ApprovalRouteDbContext.cs | 6 ++- ... 20260723074943_InitialCreate.Designer.cs} | 41 +++++++++++-------- ...ate.cs => 20260723074943_InitialCreate.cs} | 32 ++++++++------- .../ApprovalRouteDbContextModelSnapshot.cs | 39 ++++++++++-------- 8 files changed, 81 insertions(+), 59 deletions(-) create mode 100644 backend/src/Tnsu.ApprovalRoute.Domain/Enums/HeadType.cs rename backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/{20260722130455_InitialCreate.Designer.cs => 20260723074943_InitialCreate.Designer.cs} (83%) rename backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/{20260722130455_InitialCreate.cs => 20260723074943_InitialCreate.cs} (77%) diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRoute.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRoute.cs index 6d3d941..e400384 100644 --- a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRoute.cs +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRoute.cs @@ -9,7 +9,7 @@ public class TemplateRoute public Guid RequestTypeId { get; set; } // Внешние справочники (1С/ZUP) — хранятся как ссылки без FK в этой БД. - public Guid DepartmentId { get; set; } + public Guid? DepartmentId { get; set; } public Guid CompanyId { get; set; } public bool ByProject { get; set; } diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRouteStep.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRouteStep.cs index 098ea8a..b9590b4 100644 --- a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRouteStep.cs +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/TemplateRouteStep.cs @@ -11,8 +11,9 @@ public class TemplateRouteStep public string ExecutorEmail { get; set; } = string.Empty; public string Position { get; set; } = string.Empty; public ProjectRole ProjectRole { get; set; } = ProjectRole.None; + public HeadType HeadType { get; set; } = HeadType.None; - public RouteStepStatus Status { get; set; } = RouteStepStatus.Draft; + public RouteStepStatus Status { get; set; } = RouteStepStatus.Approval; public Guid RouteId { get; set; } public bool AllowReassignToOtherApprovers { get; set; } diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Enums/HeadType.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/HeadType.cs new file mode 100644 index 0000000..8643b83 --- /dev/null +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/HeadType.cs @@ -0,0 +1,8 @@ +namespace Tnsu.ApprovalRoute.Domain.Enums; + +public enum HeadType +{ + None, + Chief, + DirectionHead +} diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs index 77d1367..234f672 100644 --- a/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs @@ -3,11 +3,6 @@ namespace Tnsu.ApprovalRoute.Domain.Enums; public enum RouteStepStatus { None, - Draft, - OnApproval, - Approved, - InExecution, - Completed, - Returned, - Closed + Approval, + Execution } diff --git a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs index 4b57367..a746779 100644 --- a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs +++ b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs @@ -6,8 +6,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence; public class ApprovalRouteDbContext(DbContextOptions options) : DbContext(options) { public DbSet RequestTypes => Set(); - public DbSet Routes => Set(); - public DbSet RouteSteps => Set(); + public DbSet TemplateRoutes => Set(); + public DbSet TemplateRouteSteps => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -23,6 +23,7 @@ public class ApprovalRouteDbContext(DbContextOptions opt e.HasKey(x => x.Id); e.Property(x => x.RouteType).HasConversion().HasMaxLength(32).IsRequired(); e.HasOne(x => x.RequestType).WithMany(x => x.Routes).HasForeignKey(x => x.RequestTypeId); + e.HasIndex(x => new { x.RequestTypeId, x.DepartmentId, x.CompanyId, x.ByProject }).IsUnique(); }); modelBuilder.Entity(e => @@ -31,6 +32,7 @@ public class ApprovalRouteDbContext(DbContextOptions opt e.Property(x => x.ExecutorEmail).HasMaxLength(256).IsRequired(); e.Property(x => x.Position).HasMaxLength(128).IsRequired(); e.Property(x => x.ProjectRole).HasConversion().HasMaxLength(32).IsRequired(); + e.Property(x => x.HeadType).HasConversion().HasMaxLength(32).IsRequired(); e.Property(x => x.Status).HasConversion().HasMaxLength(32).IsRequired(); e.HasOne(x => x.Route).WithMany(x => x.Steps).HasForeignKey(x => x.RouteId); e.HasIndex(x => new { x.RouteId, x.OrderNo }); diff --git a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260722130455_InitialCreate.Designer.cs b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260723074943_InitialCreate.Designer.cs similarity index 83% rename from backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260722130455_InitialCreate.Designer.cs rename to backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260723074943_InitialCreate.Designer.cs index 475d855..5e82c93 100644 --- a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260722130455_InitialCreate.Designer.cs +++ b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260723074943_InitialCreate.Designer.cs @@ -12,7 +12,7 @@ using Tnsu.ApprovalRoute.Infrastructure.Persistence; namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations { [DbContext(typeof(ApprovalRouteDbContext))] - [Migration("20260722130455_InitialCreate")] + [Migration("20260723074943_InitialCreate")] partial class InitialCreate { /// @@ -50,7 +50,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations b.ToTable("request_types", (string)null); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -65,7 +65,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnType("uuid") .HasColumnName("company_id"); - b.Property("DepartmentId") + b.Property("DepartmentId") .HasColumnType("uuid") .HasColumnName("department_id"); @@ -84,15 +84,16 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnName("route_type"); b.HasKey("Id") - .HasName("pk_routes"); + .HasName("pk_template_routes"); - b.HasIndex("RequestTypeId") - .HasDatabaseName("ix_routes_request_type_id"); + b.HasIndex("RequestTypeId", "DepartmentId", "CompanyId", "ByProject") + .IsUnique() + .HasDatabaseName("ix_template_routes_request_type_id_department_id_company_id_by"); - b.ToTable("routes", (string)null); + b.ToTable("template_routes", (string)null); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RouteStep", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRouteStep", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -109,6 +110,12 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnType("character varying(256)") .HasColumnName("executor_email"); + b.Property("HeadType") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("head_type"); + b.Property("OrderNo") .HasColumnType("integer") .HasColumnName("order_no"); @@ -136,34 +143,34 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnName("status"); b.HasKey("Id") - .HasName("pk_route_steps"); + .HasName("pk_template_route_steps"); b.HasIndex("RouteId", "OrderNo") - .HasDatabaseName("ix_route_steps_route_id_order_no"); + .HasDatabaseName("ix_template_route_steps_route_id_order_no"); - b.ToTable("route_steps", (string)null); + b.ToTable("template_route_steps", (string)null); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b => { b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.RequestType", "RequestType") .WithMany("Routes") .HasForeignKey("RequestTypeId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_routes_request_types_request_type_id"); + .HasConstraintName("fk_template_routes_request_types_request_type_id"); b.Navigation("RequestType"); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RouteStep", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRouteStep", b => { - b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.Route", "Route") + b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", "Route") .WithMany("Steps") .HasForeignKey("RouteId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_route_steps_routes_route_id"); + .HasConstraintName("fk_template_route_steps_template_routes_route_id"); b.Navigation("Route"); }); @@ -173,7 +180,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations b.Navigation("Routes"); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b => { b.Navigation("Steps"); }); diff --git a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260722130455_InitialCreate.cs b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260723074943_InitialCreate.cs similarity index 77% rename from backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260722130455_InitialCreate.cs rename to backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260723074943_InitialCreate.cs index 772cbab..c9fede9 100644 --- a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260722130455_InitialCreate.cs +++ b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/20260723074943_InitialCreate.cs @@ -25,22 +25,22 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations }); migrationBuilder.CreateTable( - name: "routes", + name: "template_routes", columns: table => new { id = table.Column(type: "uuid", nullable: false), route_type = table.Column(type: "character varying(32)", maxLength: 32, nullable: false), request_type_id = table.Column(type: "uuid", nullable: false), - department_id = table.Column(type: "uuid", nullable: false), + department_id = table.Column(type: "uuid", nullable: true), company_id = table.Column(type: "uuid", nullable: false), by_project = table.Column(type: "boolean", nullable: false), requires_control = table.Column(type: "boolean", nullable: false) }, constraints: table => { - table.PrimaryKey("pk_routes", x => x.id); + table.PrimaryKey("pk_template_routes", x => x.id); table.ForeignKey( - name: "fk_routes_request_types_request_type_id", + name: "fk_template_routes_request_types_request_type_id", column: x => x.request_type_id, principalTable: "request_types", principalColumn: "id", @@ -48,7 +48,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations }); migrationBuilder.CreateTable( - name: "route_steps", + name: "template_route_steps", columns: table => new { id = table.Column(type: "uuid", nullable: false), @@ -56,40 +56,42 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations executor_email = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), position = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), project_role = table.Column(type: "character varying(32)", maxLength: 32, nullable: false), + head_type = table.Column(type: "character varying(32)", maxLength: 32, nullable: false), status = table.Column(type: "character varying(32)", maxLength: 32, nullable: false), route_id = table.Column(type: "uuid", nullable: false), allow_reassign_to_other_approvers = table.Column(type: "boolean", nullable: false) }, constraints: table => { - table.PrimaryKey("pk_route_steps", x => x.id); + table.PrimaryKey("pk_template_route_steps", x => x.id); table.ForeignKey( - name: "fk_route_steps_routes_route_id", + name: "fk_template_route_steps_template_routes_route_id", column: x => x.route_id, - principalTable: "routes", + principalTable: "template_routes", principalColumn: "id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateIndex( - name: "ix_route_steps_route_id_order_no", - table: "route_steps", + name: "ix_template_route_steps_route_id_order_no", + table: "template_route_steps", columns: new[] { "route_id", "order_no" }); migrationBuilder.CreateIndex( - name: "ix_routes_request_type_id", - table: "routes", - column: "request_type_id"); + name: "ix_template_routes_request_type_id_department_id_company_id_by", + table: "template_routes", + columns: new[] { "request_type_id", "department_id", "company_id", "by_project" }, + unique: true); } /// protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "route_steps"); + name: "template_route_steps"); migrationBuilder.DropTable( - name: "routes"); + name: "template_routes"); migrationBuilder.DropTable( name: "request_types"); diff --git a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/ApprovalRouteDbContextModelSnapshot.cs b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/ApprovalRouteDbContextModelSnapshot.cs index 26f31c4..c2cea76 100644 --- a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/ApprovalRouteDbContextModelSnapshot.cs +++ b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/Migrations/ApprovalRouteDbContextModelSnapshot.cs @@ -47,7 +47,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations b.ToTable("request_types", (string)null); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -62,7 +62,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnType("uuid") .HasColumnName("company_id"); - b.Property("DepartmentId") + b.Property("DepartmentId") .HasColumnType("uuid") .HasColumnName("department_id"); @@ -81,15 +81,16 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnName("route_type"); b.HasKey("Id") - .HasName("pk_routes"); + .HasName("pk_template_routes"); - b.HasIndex("RequestTypeId") - .HasDatabaseName("ix_routes_request_type_id"); + b.HasIndex("RequestTypeId", "DepartmentId", "CompanyId", "ByProject") + .IsUnique() + .HasDatabaseName("ix_template_routes_request_type_id_department_id_company_id_by"); - b.ToTable("routes", (string)null); + b.ToTable("template_routes", (string)null); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RouteStep", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRouteStep", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -106,6 +107,12 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnType("character varying(256)") .HasColumnName("executor_email"); + b.Property("HeadType") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("head_type"); + b.Property("OrderNo") .HasColumnType("integer") .HasColumnName("order_no"); @@ -133,34 +140,34 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations .HasColumnName("status"); b.HasKey("Id") - .HasName("pk_route_steps"); + .HasName("pk_template_route_steps"); b.HasIndex("RouteId", "OrderNo") - .HasDatabaseName("ix_route_steps_route_id_order_no"); + .HasDatabaseName("ix_template_route_steps_route_id_order_no"); - b.ToTable("route_steps", (string)null); + b.ToTable("template_route_steps", (string)null); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b => { b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.RequestType", "RequestType") .WithMany("Routes") .HasForeignKey("RequestTypeId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_routes_request_types_request_type_id"); + .HasConstraintName("fk_template_routes_request_types_request_type_id"); b.Navigation("RequestType"); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.RouteStep", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRouteStep", b => { - b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.Route", "Route") + b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", "Route") .WithMany("Steps") .HasForeignKey("RouteId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_route_steps_routes_route_id"); + .HasConstraintName("fk_template_route_steps_template_routes_route_id"); b.Navigation("Route"); }); @@ -170,7 +177,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations b.Navigation("Routes"); }); - modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => + modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b => { b.Navigation("Steps"); });