using System; using System.Collections.Generic; using static GB5Shared.GB5Constant.Constant; namespace GB5Shared.DTO.WorkFlow { public static class ContractsDTO { // ── Pre-check result ────────────────────────────────────────────────── /// /// Returned by CheckWorkFlowApplicability. /// Tells the caller whether a workflow is applicable and which one. /// public class WorkflowPreCheckResult { /// True when a workflow is configured and all conditions match. public bool IsEnabled { get; set; } /// /// 0 = None, 1 = Regular, 2 = WIP (form-based approval). /// public int WorkFlowMode { get; set; } /// PK of the resolved MWORKFLOW row. public int WorkFlowId { get; set; } /// PK of the matched MWORKFLOWCONFIG row (0 when no config found). public int WorkflowConfigId { get; set; } /// Whether the matched config has ISFORMBASEDAPPROVAL = 0 (0=Yes/Form-based). public bool IsFormBasedApproval { get; set; } /// /// Full URL of the entity save API used for the WIP approval callback. /// Populated from MWORKFLOWCONFIG.CALLBACKENDPOINT when IsFormBasedApproval = true. /// public string? CallbackEndpoint { get; set; } } // ── Workflow start result ───────────────────────────────────────────── /// /// Returned by StartWorkflowAsync. /// public class WorkflowStartResult { public bool IsStarted { get; set; } public bool IsWip { get; set; } public int WipId { get; set; } public int WorkflowInstanceId { get; set; } /// /// Tasks created at the first approval level. /// BLL publishes one TOUTBOX event per entry (EventTypeCode = WORKFLOW_TASK_ASSIGNED) /// AFTER the workflow transaction is committed. /// public List PendingNotifications { get; set; } = new(); /// /// Populated when the first approval level has no applicable steps and the WIP /// workflow finalises immediately at submission time (edge case). /// EventHandler dispatches this AFTER committing the transaction. /// public WipDispatchInfo? PendingDispatch { get; set; } } // ── Task notification ───────────────────────────────────────────────── /// /// Carries the data needed to publish a WORKFLOW_TASK_ASSIGNED outbox event. /// One instance is created per TWORKFLOWTASK row inserted by the engine. /// public class WorkflowTaskNotificationRequest { public int TaskId { get; set; } public int AssigneeUserId { get; set; } public int WorkflowInstanceId { get; set; } public int WorkflowId { get; set; } public object? DataJson { get; set; } /// /// JSON-serialized scalar facts from TWORKFLOWINSTANCE.FACTSJSON (DB_ENRICH bag: /// ReportingToEmployeeId, MailId, DepartmentId, etc.). /// Wrapped as {"Bag":...} and stored in OutboxDTO.ContextJson so /// EmailActionHandler can resolve recipients via DeliveryType=12 without /// an extra DB round-trip. /// public string? FactsJson { get; set; } } // ── Action result ───────────────────────────────────────────────────── /// /// Returned by HandleActionsAsync. /// PendingDispatches is populated when a WIP instance reaches final approval. /// Outcomes is populated for every terminal action (Approve-final, Reject, Return) /// so the BLL can publish outcome events after the transaction commits. /// The caller must dispatch WIP callbacks and publish outcome events AFTER committing. /// public class WorkflowActionResult { public List PendingDispatches { get; set; } = new(); public List Outcomes { get; set; } = new(); /// /// One entry per action processed by HandleActionsAsync, regardless of whether it /// was terminal for the workflow (unlike Outcomes, which only covers Approve-final / /// Reject / Return). Lets the BLL build a per-item response message (e.g. "Leave /// Request Approved Successfully") for every task the caller just acted on. /// public List ProcessedItems { get; set; } = new(); } // ── Per-item action context (for response message building) ─────────── /// /// Snapshot of the entity a single workflow task belongs to, captured for every /// action processed — used by the BLL to resolve entity type / sub-type display /// names for the caller's success message, independent of Outcomes' terminal-only /// scope. /// public class WorkflowActionItemInfo { public int TaskId { get; set; } public int WorkflowInstanceId { get; set; } /// MENTITY.ENTITYID of the document under workflow. public int EntityId { get; set; } /// PK of the document record (e.g. TaskId, LeaveId). public int ObjectId { get; set; } /// Action code taken by the caller — see . public int Action { get; set; } /// /// Serialised snapshot of the entity DTO as stored in TWORKFLOWINSTANCE.DATAJSON. /// May be a raw JSON string or a boxed object — callers must handle both. /// public object? DataJson { get; set; } } // ── Workflow outcome (Approve-final / Reject / Return) ──────────────── /// /// Carries the data needed to publish a WORKFLOW_APPROVED / WORKFLOW_REJECTED / /// WORKFLOW_RETURNED outbox event. One instance is created per terminal action /// processed by the engine (i.e. actions that change the overall workflow status /// rather than just advancing an intermediate level). /// /// For WIP workflows on Approve the WIP dispatcher already replays the entity save, /// so no outcome is emitted — /// covers that path. /// /// public class WorkflowOutcomeInfo { /// PK of the TWORKFLOWINSTANCE row. public int WorkflowInstanceId { get; set; } /// PK of the MWORKFLOW definition. public int WorkflowId { get; set; } /// MENTITY.ENTITYID of the document under workflow. public int EntityId { get; set; } /// PK of the document record (e.g. TaskId, LeaveId). public int ObjectId { get; set; } /// /// Action code — . /// 1 = Approve (final level), 2 = Reject, 3 = Return. /// public int Action { get; set; } /// UserId of the approver who took the action. public int ActionByUserId { get; set; } /// Optional comment left by the approver. public string? Comment { get; set; } /// /// Serialised snapshot of the entity DTO as stored in TWORKFLOWINSTANCE.DATAJSON. /// May be a raw JSON string or a boxed object — callers must handle both. /// public object? DataJson { get; set; } /// /// JSON-serialized scalar facts from TWORKFLOWINSTANCE.FACTSJSON. /// Written at workflow start from WorkflowStartRequest.Facts (DB_ENRICH bag values /// such as ReportingToEmployeeId, DepartmentId). /// Carried into the published Bag so /// EmailActionHandler can resolve recipients via EnrichQualifier (DeliveryType=12) /// without an extra DB round-trip. /// public string? FactsJson { get; set; } } // ── Context for applicability check ────────────────────────────────── /// /// Input to CheckWorkFlowApplicability. /// Combines all dimensions used to resolve MWORKFLOWCONFIG. /// public class WorkflowCheckContext { /// MENTITY.ENTITYID of the document being saved. public int EntityId { get; set; } /// /// OUId of the current session. Use -1 when not relevant. /// Populated from LoginDTO.WorkOUId. /// public int OUId { get; set; } = -1; /// MBIZTRANSACTIONCLASS.BIZTRANSACTIONCLASSID. Use -1 when not relevant. public int BizTransactionClassId { get; set; } = -1; /// MBIZTRANSACTION.BIZTRANSACTIONID. Use -1 when not relevant. public int BizTransactionId { get; set; } = -1; /// /// Key/value pairs extracted from the DTO being saved. /// These are evaluated against the EVALCONDITION of MWORKFLOWCONFIG /// and each MWORKFLOWDETAIL step. /// Example: { "TaskDetailType", 2 } /// public IReadOnlyDictionary Facts { get; set; } = new Dictionary(); } // ── Context for starting a workflow ────────────────────────────────── /// /// Full context required to start a new workflow instance. /// Combines the resolution context with the document payload. /// public class WorkflowStartRequest { // -- Config resolution fields (same as WorkflowCheckContext) -------- /// Entity ID of the document. public int EntityId { get; set; } /// OUId from the session. Defaults to -1 (any OU). public int OUId { get; set; } = -1; /// BizTransactionClassId. Defaults to -1 (any). public int BizTransactionClassId { get; set; } = -1; /// BizTransactionId. Defaults to -1 (any). public int BizTransactionId { get; set; } = -1; // -- Document fields ------------------------------------------------ /// PK of the document record (e.g. TaskId). public int ObjectId { get; set; } /// Serialised snapshot of the document for audit trail. public object? DataJson { get; set; } /// Optional submitter comment. public string Comment { get; set; } = string.Empty; /// /// Runtime facts extracted from the DTO. /// Used both for config resolution and per-step condition evaluation. /// public IReadOnlyDictionary Facts { get; set; } = new Dictionary(); } // ── Action context ──────────────────────────────────────────────────── /// /// Describes a single approver action (Approve / Reject / Return / Escalate). /// public class WorkflowActionContext { /// PK of the TWORKFLOWTASK being acted on. public int TaskId { get; set; } /// UserId of the person taking the action. public int UserId { get; set; } /// /// Action code — see . /// 0=Submit 1=Approve 2=Reject 3=Return 4=Escalate /// public int Action { get; set; } /// Optional comment left by the approver. public string? Comment { get; set; } /// /// Runtime facts forwarded from the client (used for next-step condition evaluation). /// public IReadOnlyDictionary Facts { get; set; } = new Dictionary(); } // ── Simulation / graph ──────────────────────────────────────────────── public class WorkflowSimulationResult { public bool WorkflowExists { get; set; } public bool Applicable { get; set; } public string? DefinitionName { get; set; } public IList StepKeys { get; set; } = new List(); public IList Actions { get; set; } = new List(); } public class WorkflowGraph { public int EntityId { get; set; } public string EntityName { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public IList Nodes { get; set; } = new List(); public IList Edges { get; set; } = new List(); } public class WorkflowGraphNode { public long StepId { get; set; } public string StepKey { get; set; } = string.Empty; public int StepType { get; set; } public bool IsInitial { get; set; } public bool IsFinal { get; set; } } public class WorkflowGraphEdge { public long FromStepId { get; set; } public long ToStepId { get; set; } public string Trigger { get; set; } = string.Empty; } } }