diff --git a/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/.gitignore b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/.gitignore new file mode 100644 index 0000000..e865c8b --- /dev/null +++ b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/.gitignore @@ -0,0 +1,15 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/.idea.Tnsu.ApprovalRoute.iml +/modules.xml +/projectSettingsUpdater.xml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/.name b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/.name new file mode 100644 index 0000000..b44cf1f --- /dev/null +++ b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/.name @@ -0,0 +1 @@ +Tnsu.ApprovalRoute \ No newline at end of file diff --git a/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/encodings.xml b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/indexLayout.xml b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/vcs.xml b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/backend/.idea/.idea.Tnsu.ApprovalRoute/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/backend/src/Tnsu.ApprovalRoute.Api/Program.cs b/backend/src/Tnsu.ApprovalRoute.Api/Program.cs index 6a18908..a1dac74 100644 --- a/backend/src/Tnsu.ApprovalRoute.Api/Program.cs +++ b/backend/src/Tnsu.ApprovalRoute.Api/Program.cs @@ -1,3 +1,6 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Tnsu.ApprovalRoute.Application; using Tnsu.ApprovalRoute.Infrastructure; diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/RequestType.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/RequestType.cs new file mode 100644 index 0000000..2cd90e7 --- /dev/null +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/RequestType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Tnsu.ApprovalRoute.Domain.Entities; + +public class RequestType +{ + public Guid Id { get; set; } = Guid.NewGuid(); + public string Name { get; set; } = string.Empty; + public string PageUrl { get; set; } = string.Empty; + + public ICollection Routes { get; set; } = new List(); +} diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/Route.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/Route.cs new file mode 100644 index 0000000..8e531aa --- /dev/null +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/Route.cs @@ -0,0 +1,20 @@ +using Tnsu.ApprovalRoute.Domain.Enums; + +namespace Tnsu.ApprovalRoute.Domain.Entities; + +public class Route +{ + public Guid Id { get; set; } = Guid.NewGuid(); + public RouteType RouteType { get; set; } = RouteType.Sequential; + public Guid RequestTypeId { get; set; } + + // Внешние справочники (1С/ZUP) — хранятся как ссылки без FK в этой БД. + public Guid DepartmentId { get; set; } + public Guid CompanyId { get; set; } + public Guid ProjectId { get; set; } + + public bool RequiresControl { get; set; } + + public RequestType? RequestType { get; set; } + public ICollection Steps { get; set; } = new List(); +} diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Entities/RouteStep.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/RouteStep.cs new file mode 100644 index 0000000..bf01d87 --- /dev/null +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Entities/RouteStep.cs @@ -0,0 +1,19 @@ +using Tnsu.ApprovalRoute.Domain.Enums; + +namespace Tnsu.ApprovalRoute.Domain.Entities; + +public class RouteStep +{ + public Guid Id { get; set; } = Guid.NewGuid(); + public int OrderNo { get; set; } + + // Внешняя ссылка на пользователя (1С/ZUP) — без локальной таблицы Users. + public Guid ExecutorUserId { get; set; } + public string Position { get; set; } = string.Empty; + + public RouteStepStatus Status { get; set; } = RouteStepStatus.Draft; + public Guid RouteId { get; set; } + public bool AllowReassignToOtherApprovers { get; set; } + + public Route? Route { get; set; } +} diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs new file mode 100644 index 0000000..147d9d6 --- /dev/null +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteStepStatus.cs @@ -0,0 +1,12 @@ +namespace Tnsu.ApprovalRoute.Domain.Enums; + +public enum RouteStepStatus +{ + Draft, + OnApproval, + Approved, + InExecution, + Completed, + Returned, + Closed +} diff --git a/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteType.cs b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteType.cs new file mode 100644 index 0000000..4a042fa --- /dev/null +++ b/backend/src/Tnsu.ApprovalRoute.Domain/Enums/RouteType.cs @@ -0,0 +1,7 @@ +namespace Tnsu.ApprovalRoute.Domain.Enums; + +public enum RouteType +{ + Parallel, + Sequential +} diff --git a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs index 6fa2086..c845852 100644 --- a/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs +++ b/backend/src/Tnsu.ApprovalRoute.Infrastructure/Persistence/ApprovalRouteDbContext.cs @@ -1,7 +1,40 @@ using Microsoft.EntityFrameworkCore; +using Tnsu.ApprovalRoute.Domain.Entities; namespace Tnsu.ApprovalRoute.Infrastructure.Persistence; public class ApprovalRouteDbContext(DbContextOptions options) : DbContext(options) { + public DbSet RequestTypes => Set(); + public DbSet Routes => Set(); + public DbSet RouteSteps => Set(); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(e => + { + e.ToTable("request_types"); + e.HasKey(x => x.Id); + e.Property(x => x.Name).HasMaxLength(256).IsRequired(); + e.Property(x => x.PageUrl).HasMaxLength(512).IsRequired(); + }); + + modelBuilder.Entity(e => + { + e.ToTable("routes"); + 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); + }); + + modelBuilder.Entity(e => + { + e.ToTable("route_steps"); + e.HasKey(x => x.Id); + e.Property(x => x.Position).HasMaxLength(128).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 }); + }); + } }