апи для работы с маршрутами согласования #2

Merged
admin merged 38 commits from initial-api into main 2026-07-27 13:14:32 +00:00
8 changed files with 81 additions and 59 deletions
Showing only changes of commit 719cd81391 - Show all commits
@@ -9,7 +9,7 @@ public class TemplateRoute
public Guid RequestTypeId { get; set; } public Guid RequestTypeId { get; set; }
// Внешние справочники (1С/ZUP) — хранятся как ссылки без FK в этой БД. // Внешние справочники (1С/ZUP) — хранятся как ссылки без FK в этой БД.
public Guid DepartmentId { get; set; } public Guid? DepartmentId { get; set; }
public Guid CompanyId { get; set; } public Guid CompanyId { get; set; }
public bool ByProject { get; set; } public bool ByProject { get; set; }
@@ -11,8 +11,9 @@ public class TemplateRouteStep
public string ExecutorEmail { get; set; } = string.Empty; public string ExecutorEmail { get; set; } = string.Empty;
public string Position { get; set; } = string.Empty; public string Position { get; set; } = string.Empty;
public ProjectRole ProjectRole { get; set; } = ProjectRole.None; 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 Guid RouteId { get; set; }
public bool AllowReassignToOtherApprovers { get; set; } public bool AllowReassignToOtherApprovers { get; set; }
@@ -0,0 +1,8 @@
namespace Tnsu.ApprovalRoute.Domain.Enums;
public enum HeadType
{
None,
Chief,
DirectionHead
}
@@ -3,11 +3,6 @@ namespace Tnsu.ApprovalRoute.Domain.Enums;
public enum RouteStepStatus public enum RouteStepStatus
{ {
None, None,
Draft, Approval,
OnApproval, Execution
Approved,
InExecution,
Completed,
Returned,
Closed
} }
@@ -6,8 +6,8 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence;
public class ApprovalRouteDbContext(DbContextOptions<ApprovalRouteDbContext> options) : DbContext(options) public class ApprovalRouteDbContext(DbContextOptions<ApprovalRouteDbContext> options) : DbContext(options)
{ {
public DbSet<RequestType> RequestTypes => Set<RequestType>(); public DbSet<RequestType> RequestTypes => Set<RequestType>();
public DbSet<TemplateRoute> Routes => Set<TemplateRoute>(); public DbSet<TemplateRoute> TemplateRoutes => Set<TemplateRoute>();
public DbSet<TemplateRouteStep> RouteSteps => Set<TemplateRouteStep>(); public DbSet<TemplateRouteStep> TemplateRouteSteps => Set<TemplateRouteStep>();
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@@ -23,6 +23,7 @@ public class ApprovalRouteDbContext(DbContextOptions<ApprovalRouteDbContext> opt
e.HasKey(x => x.Id); e.HasKey(x => x.Id);
e.Property(x => x.RouteType).HasConversion<string>().HasMaxLength(32).IsRequired(); e.Property(x => x.RouteType).HasConversion<string>().HasMaxLength(32).IsRequired();
e.HasOne(x => x.RequestType).WithMany(x => x.Routes).HasForeignKey(x => x.RequestTypeId); 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<TemplateRouteStep>(e => modelBuilder.Entity<TemplateRouteStep>(e =>
@@ -31,6 +32,7 @@ public class ApprovalRouteDbContext(DbContextOptions<ApprovalRouteDbContext> opt
e.Property(x => x.ExecutorEmail).HasMaxLength(256).IsRequired(); e.Property(x => x.ExecutorEmail).HasMaxLength(256).IsRequired();
e.Property(x => x.Position).HasMaxLength(128).IsRequired(); e.Property(x => x.Position).HasMaxLength(128).IsRequired();
e.Property(x => x.ProjectRole).HasConversion<string>().HasMaxLength(32).IsRequired(); e.Property(x => x.ProjectRole).HasConversion<string>().HasMaxLength(32).IsRequired();
e.Property(x => x.HeadType).HasConversion<string>().HasMaxLength(32).IsRequired();
e.Property(x => x.Status).HasConversion<string>().HasMaxLength(32).IsRequired(); e.Property(x => x.Status).HasConversion<string>().HasMaxLength(32).IsRequired();
e.HasOne(x => x.Route).WithMany(x => x.Steps).HasForeignKey(x => x.RouteId); e.HasOne(x => x.Route).WithMany(x => x.Steps).HasForeignKey(x => x.RouteId);
e.HasIndex(x => new { x.RouteId, x.OrderNo }); e.HasIndex(x => new { x.RouteId, x.OrderNo });
@@ -12,7 +12,7 @@ using Tnsu.ApprovalRoute.Infrastructure.Persistence;
namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
{ {
[DbContext(typeof(ApprovalRouteDbContext))] [DbContext(typeof(ApprovalRouteDbContext))]
[Migration("20260722130455_InitialCreate")] [Migration("20260723074943_InitialCreate")]
partial class InitialCreate partial class InitialCreate
{ {
/// <inheritdoc /> /// <inheritdoc />
@@ -50,7 +50,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
b.ToTable("request_types", (string)null); b.ToTable("request_types", (string)null);
}); });
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -65,7 +65,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("uuid") .HasColumnType("uuid")
.HasColumnName("company_id"); .HasColumnName("company_id");
b.Property<Guid>("DepartmentId") b.Property<Guid?>("DepartmentId")
.HasColumnType("uuid") .HasColumnType("uuid")
.HasColumnName("department_id"); .HasColumnName("department_id");
@@ -84,15 +84,16 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnName("route_type"); .HasColumnName("route_type");
b.HasKey("Id") b.HasKey("Id")
.HasName("pk_routes"); .HasName("pk_template_routes");
b.HasIndex("RequestTypeId") b.HasIndex("RequestTypeId", "DepartmentId", "CompanyId", "ByProject")
.HasDatabaseName("ix_routes_request_type_id"); .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<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -109,6 +110,12 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("character varying(256)") .HasColumnType("character varying(256)")
.HasColumnName("executor_email"); .HasColumnName("executor_email");
b.Property<string>("HeadType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)")
.HasColumnName("head_type");
b.Property<int>("OrderNo") b.Property<int>("OrderNo")
.HasColumnType("integer") .HasColumnType("integer")
.HasColumnName("order_no"); .HasColumnName("order_no");
@@ -136,34 +143,34 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnName("status"); .HasColumnName("status");
b.HasKey("Id") b.HasKey("Id")
.HasName("pk_route_steps"); .HasName("pk_template_route_steps");
b.HasIndex("RouteId", "OrderNo") 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") b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.RequestType", "RequestType")
.WithMany("Routes") .WithMany("Routes")
.HasForeignKey("RequestTypeId") .HasForeignKey("RequestTypeId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired() .IsRequired()
.HasConstraintName("fk_routes_request_types_request_type_id"); .HasConstraintName("fk_template_routes_request_types_request_type_id");
b.Navigation("RequestType"); 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") .WithMany("Steps")
.HasForeignKey("RouteId") .HasForeignKey("RouteId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired() .IsRequired()
.HasConstraintName("fk_route_steps_routes_route_id"); .HasConstraintName("fk_template_route_steps_template_routes_route_id");
b.Navigation("Route"); b.Navigation("Route");
}); });
@@ -173,7 +180,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
b.Navigation("Routes"); b.Navigation("Routes");
}); });
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
{ {
b.Navigation("Steps"); b.Navigation("Steps");
}); });
@@ -25,22 +25,22 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
}); });
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "routes", name: "template_routes",
columns: table => new columns: table => new
{ {
id = table.Column<Guid>(type: "uuid", nullable: false), id = table.Column<Guid>(type: "uuid", nullable: false),
route_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false), route_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
request_type_id = table.Column<Guid>(type: "uuid", nullable: false), request_type_id = table.Column<Guid>(type: "uuid", nullable: false),
department_id = table.Column<Guid>(type: "uuid", nullable: false), department_id = table.Column<Guid>(type: "uuid", nullable: true),
company_id = table.Column<Guid>(type: "uuid", nullable: false), company_id = table.Column<Guid>(type: "uuid", nullable: false),
by_project = table.Column<bool>(type: "boolean", nullable: false), by_project = table.Column<bool>(type: "boolean", nullable: false),
requires_control = table.Column<bool>(type: "boolean", nullable: false) requires_control = table.Column<bool>(type: "boolean", nullable: false)
}, },
constraints: table => constraints: table =>
{ {
table.PrimaryKey("pk_routes", x => x.id); table.PrimaryKey("pk_template_routes", x => x.id);
table.ForeignKey( 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, column: x => x.request_type_id,
principalTable: "request_types", principalTable: "request_types",
principalColumn: "id", principalColumn: "id",
@@ -48,7 +48,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
}); });
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "route_steps", name: "template_route_steps",
columns: table => new columns: table => new
{ {
id = table.Column<Guid>(type: "uuid", nullable: false), id = table.Column<Guid>(type: "uuid", nullable: false),
@@ -56,40 +56,42 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
executor_email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false), executor_email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
position = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false), position = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
project_role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false), project_role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
head_type = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false), status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
route_id = table.Column<Guid>(type: "uuid", nullable: false), route_id = table.Column<Guid>(type: "uuid", nullable: false),
allow_reassign_to_other_approvers = table.Column<bool>(type: "boolean", nullable: false) allow_reassign_to_other_approvers = table.Column<bool>(type: "boolean", nullable: false)
}, },
constraints: table => constraints: table =>
{ {
table.PrimaryKey("pk_route_steps", x => x.id); table.PrimaryKey("pk_template_route_steps", x => x.id);
table.ForeignKey( table.ForeignKey(
name: "fk_route_steps_routes_route_id", name: "fk_template_route_steps_template_routes_route_id",
column: x => x.route_id, column: x => x.route_id,
principalTable: "routes", principalTable: "template_routes",
principalColumn: "id", principalColumn: "id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "ix_route_steps_route_id_order_no", name: "ix_template_route_steps_route_id_order_no",
table: "route_steps", table: "template_route_steps",
columns: new[] { "route_id", "order_no" }); columns: new[] { "route_id", "order_no" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "ix_routes_request_type_id", name: "ix_template_routes_request_type_id_department_id_company_id_by",
table: "routes", table: "template_routes",
column: "request_type_id"); columns: new[] { "request_type_id", "department_id", "company_id", "by_project" },
unique: true);
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "route_steps"); name: "template_route_steps");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "routes"); name: "template_routes");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "request_types"); name: "request_types");
@@ -47,7 +47,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
b.ToTable("request_types", (string)null); b.ToTable("request_types", (string)null);
}); });
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -62,7 +62,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("uuid") .HasColumnType("uuid")
.HasColumnName("company_id"); .HasColumnName("company_id");
b.Property<Guid>("DepartmentId") b.Property<Guid?>("DepartmentId")
.HasColumnType("uuid") .HasColumnType("uuid")
.HasColumnName("department_id"); .HasColumnName("department_id");
@@ -81,15 +81,16 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnName("route_type"); .HasColumnName("route_type");
b.HasKey("Id") b.HasKey("Id")
.HasName("pk_routes"); .HasName("pk_template_routes");
b.HasIndex("RequestTypeId") b.HasIndex("RequestTypeId", "DepartmentId", "CompanyId", "ByProject")
.HasDatabaseName("ix_routes_request_type_id"); .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<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -106,6 +107,12 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnType("character varying(256)") .HasColumnType("character varying(256)")
.HasColumnName("executor_email"); .HasColumnName("executor_email");
b.Property<string>("HeadType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)")
.HasColumnName("head_type");
b.Property<int>("OrderNo") b.Property<int>("OrderNo")
.HasColumnType("integer") .HasColumnType("integer")
.HasColumnName("order_no"); .HasColumnName("order_no");
@@ -133,34 +140,34 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
.HasColumnName("status"); .HasColumnName("status");
b.HasKey("Id") b.HasKey("Id")
.HasName("pk_route_steps"); .HasName("pk_template_route_steps");
b.HasIndex("RouteId", "OrderNo") 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") b.HasOne("Tnsu.ApprovalRoute.Domain.Entities.RequestType", "RequestType")
.WithMany("Routes") .WithMany("Routes")
.HasForeignKey("RequestTypeId") .HasForeignKey("RequestTypeId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired() .IsRequired()
.HasConstraintName("fk_routes_request_types_request_type_id"); .HasConstraintName("fk_template_routes_request_types_request_type_id");
b.Navigation("RequestType"); 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") .WithMany("Steps")
.HasForeignKey("RouteId") .HasForeignKey("RouteId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired() .IsRequired()
.HasConstraintName("fk_route_steps_routes_route_id"); .HasConstraintName("fk_template_route_steps_template_routes_route_id");
b.Navigation("Route"); b.Navigation("Route");
}); });
@@ -170,7 +177,7 @@ namespace Tnsu.ApprovalRoute.Infrastructure.Persistence.Migrations
b.Navigation("Routes"); b.Navigation("Routes");
}); });
modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.Route", b => modelBuilder.Entity("Tnsu.ApprovalRoute.Domain.Entities.TemplateRoute", b =>
{ {
b.Navigation("Steps"); b.Navigation("Steps");
}); });