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<WorkflowVersion> WorkflowVersions { get; set; }
|
||||||
public DbSet<Activity> Activities { get; set; }
|
public DbSet<Activity> Activities { get; set; }
|
||||||
public DbSet<ActivityTask> ActivityTasks { 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))]
|
[ForeignKey(nameof(ParentId))]
|
||||||
public virtual ActivityTask ParentTask { get; set; } = null!;
|
public virtual ActivityTask ParentTask { get; set; } = null!;
|
||||||
|
|
||||||
|
public ICollection<ActivityAssignment> Assignments { get; set; } = [];
|
||||||
|
|
||||||
public ICollection<ActivityTask> Tasks { get; set; } = [];
|
public ICollection<ActivityTask> Tasks { get; set; } = [];
|
||||||
|
|
||||||
public List<string> Outcomes { get; set; } = [];
|
public List<string> Outcomes { get; set; } = [];
|
||||||
|
|||||||
@ -6,4 +6,5 @@ public interface IActivity : IDatabaseCore
|
|||||||
{
|
{
|
||||||
DbSet<Activity> Activities { get; set; }
|
DbSet<Activity> Activities { get; set; }
|
||||||
DbSet<ActivityTask> ActivityTasks { 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");
|
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 =>
|
modelBuilder.Entity("e_suite.Database.Core.Tables.Activity.ActivityTask", b =>
|
||||||
{
|
{
|
||||||
b.Property<long>("Id")
|
b.Property<long>("Id")
|
||||||
@ -1785,6 +1834,29 @@ namespace esuite.Database.SqlServer.Migrations
|
|||||||
b.Navigation("WorkflowVersion");
|
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 =>
|
modelBuilder.Entity("e_suite.Database.Core.Tables.Activity.ActivityTask", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("e_suite.Database.Core.Tables.Activity.Activity", "Activity")
|
b.HasOne("e_suite.Database.Core.Tables.Activity.Activity", "Activity")
|
||||||
|
|||||||
@ -43,7 +43,9 @@ public class ActivityRepository : RepositoryBase, IActivityRepository
|
|||||||
CancellationToken cancellationToken
|
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);
|
await DatabaseDbContext.SaveChangesAsync(auditUserDetails, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
using e_suite.API.Common.repository;
|
using e_suite.API.Common.repository;
|
||||||
using e_suite.Database.Audit;
|
using e_suite.Database.Audit;
|
||||||
using e_suite.Database.Core.Tables.Activity;
|
using e_suite.Database.Core.Tables.Activity;
|
||||||
|
using e_suite.Database.Core.Tables.Domain;
|
||||||
using e_suite.Messaging.Common;
|
using e_suite.Messaging.Common;
|
||||||
using e_suite.Workflow.Core;
|
using e_suite.Workflow.Core;
|
||||||
using e_suite.Workflow.Core.Extensions;
|
using e_suite.Workflow.Core.Extensions;
|
||||||
|
using e_suite.Workflow.Core.Interfaces;
|
||||||
using eSuite.Core.Clock;
|
using eSuite.Core.Clock;
|
||||||
using eSuite.Core.Enums;
|
using eSuite.Core.Enums;
|
||||||
using eSuite.Core.Miscellaneous;
|
using eSuite.Core.Miscellaneous;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
namespace e_suite.Service.WorkflowProcessor;
|
namespace e_suite.Service.WorkflowProcessor;
|
||||||
|
|
||||||
@ -168,8 +171,11 @@ public class WorkflowProcessor : IWorkflowProcessor
|
|||||||
TaskType = task.GetType().FullName!,
|
TaskType = task.GetType().FullName!,
|
||||||
TaskName = task.Name,
|
TaskName = task.Name,
|
||||||
ActivityOrdinal = activityOrdinalCounter++,
|
ActivityOrdinal = activityOrdinalCounter++,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (task is IAssignees assignableTask)
|
||||||
|
activityTask.Assignments = await GenerateAssignmentForTask(activityTask, assignableTask, auditUserDetails, cancellationToken );
|
||||||
|
|
||||||
activityTasks.Add(activityTask);
|
activityTasks.Add(activityTask);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -177,4 +183,47 @@ public class WorkflowProcessor : IWorkflowProcessor
|
|||||||
|
|
||||||
return activityTasks;
|
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;
|
namespace e_suite.Workflow.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface IAssignees
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[TaskCapability]
|
[TaskCapability]
|
||||||
public interface IAssignees<T> where T : ITaskAssignee
|
public interface IAssignees<T> : IAssignees where T : ITaskAssignee
|
||||||
{
|
{
|
||||||
[Required]
|
[Required]
|
||||||
List<T> Assignees { get; set; }
|
List<T> Assignees { get; set; }
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using e_suite.Database.Core.Tables.Domain;
|
using e_suite.Database.Core.Tables.Domain;
|
||||||
using e_suite.Database.Core.Tables.UserManager;
|
using e_suite.Database.Core.Tables.UserManager;
|
||||||
using e_suite.Workflow.Core.Attributes;
|
using e_suite.Workflow.Core.Attributes;
|
||||||
using e_suite.Workflow.Core.Enums;
|
using eSuite.Core.Workflow;
|
||||||
|
|
||||||
namespace e_suite.Workflow.Core.Interfaces;
|
namespace e_suite.Workflow.Core.Interfaces;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
using e_suite.Database.Core.Tables.Domain;
|
using e_suite.Database.Core.Tables.Domain;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using e_suite.Database.Core.Tables.UserManager;
|
using e_suite.Database.Core.Tables.UserManager;
|
||||||
using e_suite.Workflow.Core.Enums;
|
|
||||||
using e_suite.Workflow.Core.Interfaces;
|
using e_suite.Workflow.Core.Interfaces;
|
||||||
|
using eSuite.Core.Workflow;
|
||||||
|
|
||||||
namespace e_suite.Workflow.Core;
|
namespace e_suite.Workflow.Core;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user