Bounded Context: Approvals
Aggregate Root: ApprovalWorkflow
Module: Ums.Domain.Approvals.ApprovalWorkflow
Status: Production
The ApprovalWorkflow aggregate establishes dynamic routing rules and document checklists for operations requiring administrative oversight. It ensures that certain user actions—such as requesting profile promotions or submitting sensitive files—trigger the appropriate human authorization flows and define what supporting files are mandatory. It specifies the mappings of a particular document classification (e.g. Identity Proof, Contract) that are declared as mandatory requirements.
DocumentTypeId mandatory for a workflow context.IsMandatory = true).ApprovalWorkflow is the aggregate root. Adding or removing required documents must flow through it to maintain integrity. ApprovalRequiredDocument cannot exist or be modified outside the scope of its parent ApprovalWorkflow.
ApprovalWorkflow must follow the code-name-description corporate template.Code parameter must be unique within the active TenantId.RequiresApproval is true, the workflow must have at least one valid approver group or checklist criteria defined.ApprovalRequiredDocument must contain a valid WorkflowId and DocumentTypeId.ApprovalRequiredDocument must have a valid Id (Guid-based ApprovalRequiredDocumentId).ApprovalRequiredDocument is bound to the parent ApprovalWorkflow.| Entity / VO | Type | Ownership |
|—|—|—|
| ApprovalWorkflowId | Value Object | Guid-based aggregate root identifier |
| ApprovalRequiredDocument | Entity | Owned |
| ApprovalRequiredDocumentId | Value Object | Entity unique identifier |
| DocumentTypeId | Value Object | Guid reference to document classification |
| UserCategory | Enum | INTERNAL · EXTERNAL · AUDITOR |
| AuditValueObject | Value Object | Tracks creation and modification metadata |
| Event | Trigger |
|—|—|
| ApprovalWorkflowCreatedEvent | A new workflow definition is registered |
| RequiredDocumentAddedEvent | A document requirement mapping is added to the checklist |
| RequiredDocumentRemovedEvent | A document requirement mapping is removed |
| Command | Description |
|—|—|
| CreateApprovalWorkflowCommand | Initialize a new approval workflow mapping |
| AddRequiredDocumentToWorkflowCommand | Bind a DocumentType as a mandate to complete the workflow |
| RemoveRequiredDocumentFromWorkflowCommand | Remove a DocumentType constraint from the checklist |
IApprovalWorkflowRepository — Persists and loads workflows.TenantId session.ApprovalWorkflow (Aggregate Root)
├── Props: ApprovalWorkflowProps
│ ├── Id: ApprovalWorkflowId
│ ├── TenantId: TenantId
│ ├── SystemSuiteId?: SystemSuiteId
│ ├── Code: Code
│ ├── Name: Name
│ ├── Description: Description
│ ├── TargetUserCategory: UserCategory
│ ├── RequiresApproval: bool
│ └── Audit: AuditValueObject
└── Children
└── IReadOnlyCollection<ApprovalRequiredDocument>
└── Props: ApprovalRequiredDocumentProps
├── Id: ApprovalRequiredDocumentId
├── WorkflowId: ApprovalWorkflowId
├── DocumentTypeId: DocumentTypeId
├── IsMandatory: bool
└── Audit: AuditValueObject
classDiagram
direction LR
class ApprovalWorkflow {
+Guid Id
+Guid TenantId
+Guid? SystemSuiteId
+Code Code
+Name Name
+Description Description
+UserCategory TargetUserCategory
+bool RequiresApproval
+List~ApprovalRequiredDocument~ RequiredDocuments
+Create()
+AddRequiredDocument()
+RemoveRequiredDocument()
}
class UserCategory {
<<enumeration>>
INTERNAL
EXTERNAL
AUDITOR
}
class ApprovalRequiredDocument {
+Guid Id
+Guid WorkflowId
+Guid DocumentTypeId
+bool IsMandatory
+Create()
}
ApprovalWorkflow "1" *-- "0..*" ApprovalRequiredDocument
ApprovalWorkflow "1" *-- "1" UserCategory
sequenceDiagram
participant C as TenantAdmin
participant H as AddDocHandler
participant R as IApprovalWorkflowRepository
participant W as ApprovalWorkflow (AR)
C->>H: AddRequiredDocumentToWorkflowCommand(workflowId, docTypeId, isMandatory)
H->>R: GetById(workflowId)
R-->>H: ApprovalWorkflow (AR)
H->>W: AddRequiredDocument(docTypeId, isMandatory, actorId)
W->>W: Validate document type uniqueness
W->>W: Raise RequiredDocumentAddedEvent
H->>R: Save(workflow)
R-->>H: ok
H-->>C: ok
erDiagram
TENANT ||--o{ APPROVAL_WORKFLOW : "governs"
SYSTEM_SUITE ||--o{ APPROVAL_WORKFLOW : "scopes"
APPROVAL_WORKFLOW ||--o{ APPROVAL_REQUIRED_DOCUMENT : "demands"
DOCUMENT_TYPE ||--o{ APPROVAL_REQUIRED_DOCUMENT : "defines"
APPROVAL_WORKFLOW {
uniqueidentifier WorkflowId PK
uniqueidentifier TenantId FK
uniqueidentifier SystemSuiteId FK "Nullable"
nvarchar Code "Unique per TenantId"
nvarchar Name
nvarchar Description
nvarchar TargetUserCategory "INTERNAL-EXTERNAL-AUDITOR"
bit RequiresApproval
datetime2 UpdatedAt
uniqueidentifier UpdatedBy
}
APPROVAL_REQUIRED_DOCUMENT {
uniqueidentifier RequiredDocId PK
uniqueidentifier WorkflowId FK
uniqueidentifier DocumentTypeId FK
bit IsMandatory
}
DOCUMENT_TYPE {
uniqueidentifier DocumentTypeId PK
}
APPROVAL_WORKFLOW records are partitioned by TenantId. Direct database queries require application repository filtering (R-10).APPROVAL_REQUIRED_DOCUMENT acknowledges parent-level tenant scoping rules. Inherits database isolation rules of APPROVAL_WORKFLOW.SystemSuiteId from Authorization context.ApprovalRequest to verify submission checklists, and PromotionRequest in IGA context to check authorization mandates. Mapped internally inside the Approvals context. Directly targets DocumentType configurations.CreateApprovalWorkflowCommand -> Inputs: TenantId, Code, Name, Description, UserCategory, RequiresApproval, SystemSuiteId? -> Returns: GuidAddRequiredDocumentToWorkflowCommand -> Inputs: WorkflowId, DocumentTypeId, IsMandatory -> Returns: voidRemoveRequiredDocumentFromWorkflowCommand -> Inputs: WorkflowId, DocumentTypeId -> Returns: voidTenantId, Code to avoid overlapping codes.RequiredDocId and composite index on WorkflowId, DocumentTypeId.Tenant:Admin or higher roles.ApprovalWorkflow. Only users authorized to design workflows can configure these mappings.