Runtime Assignments are now created in the database when the activity is planned.
This commit is contained in:
parent
7048594ea9
commit
a12731142c
@ -75,4 +75,5 @@ public class EsuiteDatabaseDbContext : SunDatabaseEntityContext, IEsuiteDatabase
|
||||
public DbSet<WorkflowVersion> WorkflowVersions { get; set; }
|
||||
public DbSet<Activity> Activities { get; set; }
|
||||
public DbSet<ActivityTask> ActivityTasks { get; set; }
|
||||
public DbSet<ActivityAssignment> ActivityAssignments { get; set; }
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using e_suite.Database.Audit.Attributes;
|
||||
using e_suite.Database.Core.Models;
|
||||
using e_suite.Database.Core.Tables.Domain;
|
||||
using e_suite.Database.Core.Tables.UserManager;
|
||||
using eSuite.Core.Workflow;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace e_suite.Database.Core.Tables.Activity;
|
||||
|
||||
[DisplayName("Activity Assignment")]
|
||||
[Table("ActivityAssignments", Schema = "Activity")]
|
||||
[Index(nameof(Guid), IsUnique = true)]
|
||||
public class ActivityAssignment : IGeneralId, ISoftDeletable
|
||||
{
|
||||
[Key]
|
||||
public long Id { get; set; }
|
||||
|
||||
public Guid Guid { get; set; }
|
||||
|
||||
[AuditSoftDelete(true)]
|
||||
[Required]
|
||||
[DefaultValue(false)]
|
||||
public bool Deleted { get; set; }
|
||||
|
||||
public long TaskId { get; set; }
|
||||
|
||||
|
||||
public Raci Raci { get; set; }
|
||||
|
||||
public long? RoleId { get; set; }
|
||||
|
||||
public long? UserId { get; set; }
|
||||
|
||||
public bool AllowNoVerdict { get; set; } = false;
|
||||
|
||||
public bool Bypassable { get; set; } = false;
|
||||
|
||||
[AuditLastUpdated]
|
||||
public DateTimeOffset LastUpdated { get; set; }
|
||||
|
||||
[AuditParent]
|
||||
[ForeignKey(nameof(TaskId))]
|
||||
public virtual ActivityTask Task { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(RoleId))]
|
||||
public virtual Role Role { get; set; } = null!;
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public virtual User User { get; set; } = null!;
|
||||
}
|
||||
@ -68,6 +68,8 @@ public class ActivityTask : IGeneralId, ISoftDeletable
|
||||
[ForeignKey(nameof(ParentId))]
|
||||
public virtual ActivityTask ParentTask { get; set; } = null!;
|
||||
|
||||
public ICollection<ActivityAssignment> Assignments { get; set; } = [];
|
||||
|
||||
public ICollection<ActivityTask> Tasks { get; set; } = [];
|
||||
|
||||
public List<string> Outcomes { get; set; } = [];
|
||||
|
||||
@ -6,4 +6,5 @@ public interface IActivity : IDatabaseCore
|
||||
{
|
||||
DbSet<Activity> Activities { get; set; }
|
||||
DbSet<ActivityTask> ActivityTasks { get; set; }
|
||||
DbSet<ActivityAssignment> ActivityAssignments { get; set; }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace esuite.Database.SqlServer.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class addingactivityassignments : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ActivityAssignments",
|
||||
schema: "Activity",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
Guid = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Deleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
TaskId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Raci = table.Column<int>(type: "int", nullable: false),
|
||||
RoleId = table.Column<long>(type: "bigint", nullable: true),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: true),
|
||||
AllowNoVerdict = table.Column<bool>(type: "bit", nullable: false),
|
||||
Bypassable = table.Column<bool>(type: "bit", nullable: false),
|
||||
LastUpdated = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ActivityAssignments", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ActivityAssignments_ActivityTasks_TaskId",
|
||||
column: x => x.TaskId,
|
||||
principalSchema: "Activity",
|
||||
principalTable: "ActivityTasks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_ActivityAssignments_Roles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalSchema: "Domain",
|
||||
principalTable: "Roles",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_ActivityAssignments_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalSchema: "UserManager",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ActivityAssignments_Guid",
|
||||
schema: "Activity",
|
||||
table: "ActivityAssignments",
|
||||
column: "Guid",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ActivityAssignments_RoleId",
|
||||
schema: "Activity",
|
||||
table: "ActivityAssignments",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ActivityAssignments_TaskId",
|
||||
schema: "Activity",
|
||||
table: "ActivityAssignments",
|
||||
column: "TaskId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ActivityAssignments_UserId",
|
||||
schema: "Activity",
|
||||
table: "ActivityAssignments",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ActivityAssignments",
|
||||
schema: "Activity");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -154,6 +154,55 @@ namespace esuite.Database.SqlServer.Migrations
|
||||
b.ToTable("Activities", "Activity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("e_suite.Database.Core.Tables.Activity.ActivityAssignment", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<bool>("AllowNoVerdict")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("Bypassable")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("Deleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<Guid>("Guid")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTimeOffset>("LastUpdated")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<int>("Raci")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("RoleId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("TaskId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Guid")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ActivityAssignments", "Activity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("e_suite.Database.Core.Tables.Activity.ActivityTask", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
@ -1785,6 +1834,29 @@ namespace esuite.Database.SqlServer.Migrations
|
||||
b.Navigation("WorkflowVersion");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("e_suite.Database.Core.Tables.Activity.ActivityAssignment", b =>
|
||||
{
|
||||
b.HasOne("e_suite.Database.Core.Tables.Domain.Role", "Role")
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId");
|
||||
|
||||
b.HasOne("e_suite.Database.Core.Tables.Activity.ActivityTask", "task")
|
||||
.WithMany()
|
||||
.HasForeignKey("TaskId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("e_suite.Database.Core.Tables.UserManager.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Role");
|
||||
|
||||
b.Navigation("User");
|
||||
|
||||
b.Navigation("task");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("e_suite.Database.Core.Tables.Activity.ActivityTask", b =>
|
||||
{
|
||||
b.HasOne("e_suite.Database.Core.Tables.Activity.Activity", "Activity")
|
||||
|
||||
@ -43,7 +43,9 @@ public class ActivityRepository : RepositoryBase, IActivityRepository
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
DatabaseDbContext.ActivityTasks.AddRange(activityTasks);
|
||||
var enumerable = activityTasks as ActivityTask[] ?? activityTasks.ToArray();
|
||||
DatabaseDbContext.ActivityTasks.AddRange(enumerable);
|
||||
DatabaseDbContext.ActivityAssignments.AddRange(enumerable.SelectMany( x => x.Assignments));
|
||||
await DatabaseDbContext.SaveChangesAsync(auditUserDetails, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
using e_suite.API.Common.repository;
|
||||
using e_suite.Database.Audit;
|
||||
using e_suite.Database.Core.Tables.Activity;
|
||||
using e_suite.Database.Core.Tables.Domain;
|
||||
using e_suite.Messaging.Common;
|
||||
using e_suite.Workflow.Core;
|
||||
using e_suite.Workflow.Core.Extensions;
|
||||
using e_suite.Workflow.Core.Interfaces;
|
||||
using eSuite.Core.Clock;
|
||||
using eSuite.Core.Enums;
|
||||
using eSuite.Core.Miscellaneous;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections;
|
||||
|
||||
namespace e_suite.Service.WorkflowProcessor;
|
||||
|
||||
@ -168,8 +171,11 @@ public class WorkflowProcessor : IWorkflowProcessor
|
||||
TaskType = task.GetType().FullName!,
|
||||
TaskName = task.Name,
|
||||
ActivityOrdinal = activityOrdinalCounter++,
|
||||
|
||||
};
|
||||
|
||||
if (task is IAssignees assignableTask)
|
||||
activityTask.Assignments = await GenerateAssignmentForTask(activityTask, assignableTask, auditUserDetails, cancellationToken );
|
||||
|
||||
activityTasks.Add(activityTask);
|
||||
|
||||
}
|
||||
@ -177,4 +183,47 @@ public class WorkflowProcessor : IWorkflowProcessor
|
||||
|
||||
return activityTasks;
|
||||
}
|
||||
|
||||
private async Task<ICollection<ActivityAssignment>> GenerateAssignmentForTask(ActivityTask activityTask, IAssignees task, AuditUserDetails auditUserDetails, CancellationToken cancellationToken)
|
||||
{
|
||||
// Find the IAssignees<T> interface implemented by this instance
|
||||
var typedInterface = task.GetType()
|
||||
.GetInterfaces()
|
||||
.FirstOrDefault(i =>
|
||||
i.IsGenericType &&
|
||||
i.GetGenericTypeDefinition() == typeof(IAssignees<>));
|
||||
|
||||
if (typedInterface == null)
|
||||
throw new InvalidOperationException("Task does not implement IAssignees<T>.");
|
||||
|
||||
// Get the Assignees property
|
||||
var assigneesProperty = typedInterface.GetProperty("Assignees");
|
||||
var assignees = (IEnumerable)assigneesProperty.GetValue(task);
|
||||
|
||||
var results = new List<ActivityAssignment>();
|
||||
|
||||
foreach (var assignee in assignees)
|
||||
{
|
||||
var typedAssignee = (ITaskAssignee)assignee;
|
||||
|
||||
|
||||
var activityAssignment = new ActivityAssignment
|
||||
{
|
||||
Guid = Guid.NewGuid(),
|
||||
Raci = typedAssignee.Raci,
|
||||
Role = typedAssignee.Role!,
|
||||
User = typedAssignee.User!,
|
||||
};
|
||||
|
||||
if (typedAssignee is IApprovalTaskAssignee approvalAssignee)
|
||||
{
|
||||
activityAssignment.Bypassable = approvalAssignee.Bypassable;
|
||||
activityAssignment.AllowNoVerdict = approvalAssignee.AllowNoVerdict;
|
||||
}
|
||||
|
||||
results.Add(activityAssignment);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace e_suite.Workflow.Core.Enums;
|
||||
|
||||
public enum Raci
|
||||
{
|
||||
Responsible,
|
||||
Accountable,
|
||||
Consulted,
|
||||
Informed
|
||||
}
|
||||
@ -3,8 +3,13 @@ using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace e_suite.Workflow.Core.Interfaces;
|
||||
|
||||
public interface IAssignees
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[TaskCapability]
|
||||
public interface IAssignees<T> where T : ITaskAssignee
|
||||
public interface IAssignees<T> : IAssignees where T : ITaskAssignee
|
||||
{
|
||||
[Required]
|
||||
List<T> Assignees { get; set; }
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
using e_suite.Database.Core.Tables.Domain;
|
||||
using e_suite.Database.Core.Tables.UserManager;
|
||||
using e_suite.Workflow.Core.Attributes;
|
||||
using e_suite.Workflow.Core.Enums;
|
||||
using eSuite.Core.Workflow;
|
||||
|
||||
namespace e_suite.Workflow.Core.Interfaces;
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
using e_suite.Database.Core.Tables.Domain;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using e_suite.Database.Core.Tables.UserManager;
|
||||
using e_suite.Workflow.Core.Enums;
|
||||
using e_suite.Workflow.Core.Interfaces;
|
||||
using eSuite.Core.Workflow;
|
||||
|
||||
namespace e_suite.Workflow.Core;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user