using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace GB5Shared.DTO.GOP
{
// ============================================================
// GOP PLATFORM DTOs
// Maps to MGop* (master) and TGop* (transaction) SQL tables
// ClientId resolved from LoginDTO.ClientId at runtime
// ============================================================
// ── Request / Response ───────────────────────────────────────
public class GopSubmitRequestDTO
{
public string SourceCode { get; set; } = string.Empty; // e.g. "TASK_SAVE_API"
public string PayloadJson { get; set; } = string.Empty; // JSON body (task payload etc.)
// Environment is NOT accepted from the client — resolved server-side from IConfiguration["GOP:Environment"]
public string? IdempotencyKey { get; set; }
public int Priority { get; set; } = 5;
}
public class GopSubmitResponseDTO
{
public int QueueId { get; set; }
public int ExecutionId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string SnapshotVersion { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string Message { get; set; } = string.Empty;
}
public class GopOpenRemediationRequestDTO
{
public int ExecutionId { get; set; }
public int QueueId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string SnapshotVersion { get; set; } = string.Empty;
public int FailedNodeId { get; set; }
public string FailedNodeCode { get; set; } = string.Empty;
public string OriginalPayloadJson { get; set; } = string.Empty;
public string TargetResponseJson { get; set; } = string.Empty;
public string IssueListJson { get; set; } = string.Empty;
public string? AssignedTo { get; set; }
}
public class GopResolveRemediationRequestDTO
{
public int RemediationId { get; set; }
public string ResolutionNotes { get; set; } = string.Empty;
}
// ── Master: Target Operation ─────────────────────────────────
// Maps to MGOPTARGETOPERATION — the API registry used by ApiCall flow-step nodes.
public class GopTargetOperationDTO
{
public int TargetOperationId { get; set; }
public int TenantId { get; set; }
public string OperationCode { get; set; } = string.Empty;
public string OperationName { get; set; } = string.Empty;
public string BaseUrl { get; set; } = string.Empty;
public string RelativePath { get; set; } = string.Empty;
/// GET | POST | PUT | PATCH | DELETE
public string HttpMethod { get; set; } = "POST";
public string? RequestSchemaJson { get; set; }
public string? ResponseSchemaJson { get; set; }
public string? SpecHash { get; set; }
// Entity Viewer registry reuse — NULL for GOP Flow ApiCall rows.
// EntityCode matches MQUALIFIERENTITY.ENTITYCODE's convention. Populated for
// entity-CRUD rows, whose OperationCode follows '{EntityCode}.Get'/'.Save'/'.Delete'.
public string? EntityCode { get; set; }
public string? IdFieldName { get; set; }
// Both populated by GetGopTargetOperation's join from EntityCode to MENTITY —
// not persisted columns on MGOPTARGETOPERATION. NULL when EntityCode is unset
// (every GOP Flow ApiCall row).
public int? EntityId { get; set; }
public string? EntityName { get; set; }
public int Version { get; set; }
public int Status { get; set; }
public int SortOrder { get; set; }
// Audit fields — set by DAL before insert/update
public int CreatedById { get; set; }
public int ModifiedById { get; set; }
}
// Dropdown population — id/code/name only, no schema/URL payload.
public class GopTargetOperationSelectListDTO
{
public int TargetOperationId { get; set; }
public string OperationCode { get; set; } = string.Empty;
public string OperationName { get; set; } = string.Empty;
}
// ── Master: Source Binding ───────────────────────────────────
public class GopSourceBindingDTO
{
public int ClientId { get; set; }
public int SourceBindingId { get; set; }
public string SourceType { get; set; } = string.Empty; // FILE | API | EVENT
public string SourceCode { get; set; } = string.Empty;
public string SourceName { get; set; } = string.Empty;
public string? Description { get; set; }
public int FlowId { get; set; }
public string SnapshotVersion { get; set; } = string.Empty;
public string Environment { get; set; } = "PROD";
public bool IsActive { get; set; } = true;
/// Populated by joining MGOPFLOW on FlowId — not a persisted column.
public string? GopFlowName { get; set; }
}
// ── Master: Flow ─────────────────────────────────────────────
public class GopFlowDTO
{
public int ClientId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string FlowName { get; set; } = string.Empty;
public string? Description { get; set; }
public string Status { get; set; } = string.Empty;
public int Version { get; set; }
public string? DriftStatus { get; set; }
}
// ── Master: Flow Snapshot ─────────────────────────────────────
public class GopFlowSnapshotDTO
{
public int ClientId { get; set; }
public int SnapshotId { get; set; }
public int FlowId { get; set; }
public string SnapshotVersion { get; set; } = string.Empty;
public string Environment { get; set; } = string.Empty;
public string SpecAggregateHash { get; set; } = string.Empty;
public string SnapshotJson { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
public DateTime PublishedAt { get; set; }
public string PublishedBy { get; set; } = string.Empty;
}
// ── Master: Flow Step (design-time graph node) ─────────────────
// Maps to MGOPFLOWSTEP — authored via the Flow Designer, resolved into an
// immutable GopFlowSnapshotStepDTO at publish time.
public class GopFlowStepDTO
{
public int ClientId { get; set; }
public int FlowStepId { get; set; }
public int FlowId { get; set; }
public string NodeCode { get; set; } = string.Empty;
public string NodeName { get; set; } = string.Empty;
/// Qualifier | Mapper | ApiCall | Approval
public string NodeType { get; set; } = string.Empty;
public string? LogicalServiceName { get; set; }
public int TargetOperationId { get; set; } = -1;
public int TimeoutSeconds { get; set; } = 60;
public int MaxRetries { get; set; } = 3;
public bool SupportsRemediation { get; set; } = false;
public int SortOrder { get; set; }
/// Approval steps only — who a paused execution shows up assigned to.
/// Required (role or user) for an Approval step before the flow can publish.
public string? AssignedRole { get; set; }
public int? AssignedToUserId { get; set; }
/// Populated by joining MGOPFLOW on FlowId — not a persisted column.
public string? GopFlowName { get; set; }
/// Populated by joining MGOPTARGETOPERATION on TargetOperationId — not a persisted
/// column. Null for non-ApiCall steps (TargetOperationId is -1 for those).
public string? OperationName { get; set; }
}
// ── Master: Flow Step Edge (design-time DAG edge) ───────────────
// Maps to MGOPFLOWSTEPEDGE — connects two GopFlowStepDTO nodes within a flow.
public class GopFlowStepEdgeDTO
{
public int ClientId { get; set; }
public int FlowStepEdgeId { get; set; }
public int FlowId { get; set; }
public int FromStepId { get; set; }
public int ToStepId { get; set; }
/// MGOPFLOWSTEP.NODECODE of FromStepId — read-only, populated via join.
public string? FromStepName { get; set; }
/// MGOPFLOWSTEP.NODENAME of ToStepId — read-only, populated via join.
public string? ToStepName { get; set; }
public string? EdgeLabel { get; set; }
/// Always | OnSuccess | OnFailure — which outcome of FromStepId traverses this edge.
public string EdgeCondition { get; set; } = "Always";
}
// ── Combined design-time graph (steps + edges) for a flow ───────
public class GopFlowGraphDTO
{
public GopFlowDTO Flow { get; set; } = new();
public List Steps { get; set; } = new();
public List Edges { get; set; } = new();
}
// ── Master: Flow Snapshot Step Edge (immutable, resolved at publish time) ──
// Maps to MGOPFLOWSNAPSHOTSTEPEDGE — the edge set GopExecutionPipeline traverses
// at runtime. Snapshotted alongside MGOPFLOWSNAPSHOTSTEP so a flow's routing
// can't drift after publish even if the design-time graph changes later.
public class GopFlowSnapshotStepEdgeDTO
{
public int ClientId { get; set; }
public int SnapshotStepEdgeId { get; set; }
public int SnapshotId { get; set; }
public string SnapshotVersion { get; set; } = string.Empty;
public int FromNodeId { get; set; }
public int ToNodeId { get; set; }
public string? EdgeLabel { get; set; }
public string EdgeCondition { get; set; } = "Always";
}
// ── Master: Flow Snapshot Step ────────────────────────────────
public class GopFlowSnapshotStepDTO
{
public int ClientId { get; set; }
public int SnapshotStepId { get; set; }
public int SnapshotId { get; set; }
public string SnapshotVersion { get; set; } = string.Empty;
public int StepOrder { get; set; }
public int NodeId { get; set; }
public string NodeCode { get; set; } = string.Empty;
public string NodeType { get; set; } = string.Empty; // Qualifier | Mapper | ApiCall
public string LogicalServiceName { get; set; } = string.Empty;
public string ResolvedEndpoint { get; set; } = string.Empty; // base URL or INTERNAL
public string HttpMethod { get; set; } = string.Empty;
public string RelativePath { get; set; } = string.Empty;
public string? RequestSchemaJson { get; set; }
public string? ResponseSchemaJson { get; set; }
public string? MappingJson { get; set; }
public string SpecHash { get; set; } = string.Empty;
public int TimeoutSeconds { get; set; } = 60;
public int MaxRetries { get; set; } = 3;
public bool SupportsRemediation { get; set; } = false;
/// Approval steps only — copied from GopFlowStepDTO at publish time.
public string? AssignedRole { get; set; }
public int? AssignedToUserId { get; set; }
}
// ── Master: Canonical Model ────────────────────────────────────
// Maps to MCANONICALMODEL — a reusable, typed schema for one business
// entity/document (e.g. "PO", "LEAVE", "RESUME") shared across every Mapper
// that produces or consumes that document, instead of each Mapper inventing
// its own open-ended shape. EntityCode intentionally matches the EntityCode
// convention already used by MQUALIFIERENTITY.
public class GopCanonicalModelDTO
{
public int TenantId { get; set; }
public int CanonicalModelId { get; set; }
public string EntityCode { get; set; } = string.Empty;
public string ModelName { get; set; } = string.Empty;
public string? Description { get; set; }
public int Version { get; set; } = 1;
public bool IsActive { get; set; } = true;
public int SortOrder { get; set; }
public int Status { get; set; } = 1;
/// Library tier, same convention as PortletType/Dashboard/ReportView's own
/// SourceType: 1=Framework, 2=DevAdmin are protected "Standard" library rows a tenant
/// session cannot edit/deactivate (see CanonicalModelBLL.GuardSourceType). Column already
/// exists live (MCANONICALMODEL.SOURCETYPE, default 5=User) — this DTO just newly exposes
/// it; default here matches the live column default exactly.
public byte SourceType { get; set; } = 5;
}
// ── Master: Canonical Field ─────────────────────────────────────
// Maps to MCANONICALFIELD — one field of a canonical model's schema.
public class GopCanonicalFieldDTO
{
public int TenantId { get; set; }
public int CanonicalFieldId { get; set; }
public int CanonicalModelId { get; set; }
/// JSONPath into the canonical document, e.g. "$.PONumber".
public string FieldPath { get; set; } = string.Empty;
public string FieldName { get; set; } = string.Empty;
/// String | Number | Date | Bool | Array | Object
public string DataType { get; set; } = "String";
public bool IsRequired { get; set; } = false;
public string? DefaultValue { get; set; }
public string? Description { get; set; }
public int SortOrder { get; set; }
}
// ── Master: Document Type ────────────────────────────────────────
// Maps to MGOPDOCUMENTTYPE — a named, reusable "shape of an incoming source
// file/document" (e.g. "SBI Bank Statement (Excel)", "Generic CSV"), each
// optionally pointing at the GopCanonicalModelDTO its rows normally map to.
// A library of these (SourceType Framework rows) ships pre-built for popular
// formats; tenants can add their own or clone-and-customize a library one.
public class GopDocumentTypeDTO
{
public int TenantId { get; set; }
public int DocumentTypeId { get; set; }
public string EntityCode { get; set; } = string.Empty;
public string DocumentTypeName { get; set; } = string.Empty;
/// Matches IceMapDTO.IceMapIceSourceType's own enum: Excel|Json|Xml|Csv.
public string SourceFormat { get; set; } = "Excel";
/// Optional starter link — "this format normally maps to this canonical shape."
public int? DefaultCanonicalModelId { get; set; }
/// Expected classification label an AI document-identifier capability returns
/// for this document type (e.g. "RESUME") — used by GopDocumentIntakeBLL to resolve which
/// DocumentType/EntityCode (and therefore which GopSourceBinding/flow) an uploaded file
/// belongs to. Case-insensitive match, admin-editable so it can be corrected without a
/// redeploy once the real classifier's output vocabulary is confirmed. Null for rows not
/// used by the AI intake pipeline (e.g. the pre-existing Excel/CSV library rows).
public string? AiClassificationLabel { get; set; }
public string? Description { get; set; }
public int SortOrder { get; set; }
public int Status { get; set; } = 1;
/// Same Framework(1)/DevAdmin(2)=Standard tiering as GopCanonicalModelDTO's own
/// SourceType; default 5=User to match the live convention on MCANONICALMODEL/MCANONICALFIELD.
public byte SourceType { get; set; } = 5;
}
// ── Master: Qualifier Rules ───────────────────────────────────
public class GopQualifierDefinitionDTO
{
public int ClientId { get; set; }
public int QualifierId { get; set; }
public string QualifierCode { get; set; } = string.Empty;
public string QualifierName { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
}
public class GopQualifierRuleDTO
{
public int ClientId { get; set; }
public int RuleId { get; set; }
public int QualifierId { get; set; }
public int RuleOrder { get; set; }
public string RuleName { get; set; } = string.Empty;
public string FieldPath { get; set; } = string.Empty; // JSONPath e.g. $.TaskNumber
public string Operator { get; set; } = string.Empty; // NotNull | Regex | In | Range
public string? ExpectedValue { get; set; }
public string ErrorCode { get; set; } = string.Empty;
public string ErrorMessage { get; set; } = string.Empty;
public string Severity { get; set; } = "Error"; // Error | Warning
}
// ── Master: Mapper Field Rules ────────────────────────────────
public class GopMapperDefinitionDTO
{
public int ClientId { get; set; }
public int MapperId { get; set; }
public string MapperCode { get; set; } = string.Empty;
public string MapperName { get; set; } = string.Empty;
public string SourceFormat { get; set; } = string.Empty;
public string TargetFormat { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
}
public class GopMapperFieldRuleDTO
{
public int ClientId { get; set; }
public int RuleId { get; set; }
public int MapperId { get; set; }
public int RuleOrder { get; set; }
public string SourcePath { get; set; } = string.Empty;
public string TargetPath { get; set; } = string.Empty;
public string? TransformExpression { get; set; }
public string? DefaultValue { get; set; }
public bool IsRequired { get; set; } = false;
}
// ── Transaction: Execution Queue ──────────────────────────────
public class GopExecutionQueueDTO
{
public int ClientId { get; set; }
public int QueueId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string SnapshotVersion { get; set; } = string.Empty;
public string? SourceCode { get; set; }
public string PayloadJson { get; set; } = string.Empty;
public string? IdempotencyKey { get; set; }
public int Priority { get; set; } = 5;
public string Status { get; set; } = "Pending";
public int RetryCount { get; set; } = 0;
public int MaxRetry { get; set; } = 5;
public string? LeaseOwner { get; set; }
public DateTime? LeaseAt { get; set; }
public DateTime? LeaseUntil { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? CompletedAt { get; set; }
public string? ErrorMessage { get; set; }
}
// ── Transaction: Execution Header ─────────────────────────────
public class GopExecutionHeaderDTO
{
public int ClientId { get; set; }
public int ExecutionId { get; set; }
public int QueueId { get; set; }
public int? ParentExecutionId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string SnapshotVersion { get; set; } = string.Empty;
public string Status { get; set; } = "Created";
public string SourcePayloadJson { get; set; } = string.Empty;
public int? CurrentNodeId { get; set; }
public string? CurrentNodeCode { get; set; }
/// Output payload of the last successfully completed node — set when an
/// Approval-gate node pauses the pipeline, so a resumed execution continues from
/// here instead of restarting from SourcePayloadJson.
public string? LastOutputPayloadJson { get; set; }
/// Set from the paused Approval step when Status='PendingApproval' — who owns the task.
public string? AssignedRole { get; set; }
public int? AssignedToUserId { get; set; }
public DateTime StartedAt { get; set; } = DateTime.UtcNow;
public DateTime? CompletedAt { get; set; }
public long? TotalDurationMs { get; set; }
public string? ErrorMessage { get; set; }
public bool IsReplay { get; set; } = false;
}
// ── Transaction: Execution Node Log ───────────────────────────
public class GopExecutionNodeLogDTO
{
public int ClientId { get; set; }
public int NodeLogId { get; set; }
public int ExecutionId { get; set; }
public int NodeId { get; set; }
public string NodeCode { get; set; } = string.Empty;
public int StepOrder { get; set; }
public int AttemptNo { get; set; } = 1;
public string Status { get; set; } = string.Empty; // Running | Success | Failed
public string? RequestPayloadJson { get; set; }
public string? ResponsePayloadJson { get; set; }
public int? HttpStatusCode { get; set; }
public string? HttpMethod { get; set; }
public string? EndpointUrl { get; set; }
public long? DurationMs { get; set; }
public string? ErrorCode { get; set; }
public string? ErrorMessage { get; set; }
public DateTime StartedAt { get; set; } = DateTime.UtcNow;
public DateTime? CompletedAt { get; set; }
}
// ── Transaction: Execution State Log ──────────────────────────
public class GopExecutionStateLogDTO
{
public int ClientId { get; set; }
public int ExecutionId { get; set; }
public string? PreviousStatus { get; set; }
public string NewStatus { get; set; } = string.Empty;
public string? ReasonCode { get; set; }
public string? ChangedBy { get; set; }
public DateTime ChangedAt { get; set; } = DateTime.UtcNow;
}
// ── Transaction: Execution Metrics ────────────────────────────
public class GopExecutionMetricsDTO
{
public int ClientId { get; set; }
public int ExecutionId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public long TotalDurationMs { get; set; }
public int NodeCount { get; set; }
public int TotalRetries { get; set; } = 0;
public bool IsSuccess { get; set; }
public DateTime RecordedAt { get; set; } = DateTime.UtcNow;
}
// ── Transaction: Execution Node Metrics ───────────────────────
public class GopExecutionNodeMetricsDTO
{
public int ClientId { get; set; }
public int ExecutionId { get; set; }
public int NodeId { get; set; }
public string NodeCode { get; set; } = string.Empty;
public long DurationMs { get; set; }
public int RetryAttempts { get; set; } = 0;
public int? HttpStatusCode { get; set; }
public bool IsSuccess { get; set; }
public DateTime RecordedAt { get; set; } = DateTime.UtcNow;
}
// ── Transaction: Dead Letter ───────────────────────────────────
public class GopDeadLetterDTO
{
public int ClientId { get; set; }
public int DlqId { get; set; }
public int ExecutionId { get; set; }
public int QueueId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string SnapshotVersion { get; set; } = string.Empty;
public int FailedNodeId { get; set; }
public string FailedNodeCode { get; set; } = string.Empty;
public string PayloadJson { get; set; } = string.Empty;
public string ErrorMessage { get; set; } = string.Empty;
public string? ErrorStack { get; set; }
public int RetryCount { get; set; }
public string FailureCategory { get; set; } = "Transient"; // Transient | Fatal | BusinessLogic
public DateTime MovedToDlqAt { get; set; } = DateTime.UtcNow;
public bool IsResolved { get; set; } = false;
public DateTime? ResolvedAt { get; set; }
public string? ResolvedBy { get; set; }
}
// ── Transaction: Remediation ──────────────────────────────────
public class GopRemediationDTO
{
public int ClientId { get; set; }
public int RemediationId { get; set; }
public int ExecutionId { get; set; }
public int QueueId { get; set; }
public int FlowId { get; set; }
public string FlowCode { get; set; } = string.Empty;
public string SnapshotVersion { get; set; } = string.Empty;
public int FailedNodeId { get; set; }
public string FailedNodeCode { get; set; } = string.Empty;
public string OriginalPayloadJson { get; set; } = string.Empty;
public string TargetResponseJson { get; set; } = string.Empty;
public string IssueListJson { get; set; } = string.Empty;
public string Status { get; set; } = "Open"; // Open | InProgress | Resolved | Closed
public int ResubmissionCount { get; set; } = 0;
public string? AssignedTo { get; set; }
public string? ResolutionNotes { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? ResolvedAt { get; set; }
public string? ResolvedBy { get; set; }
}
// ── Transaction: Execution Lock ───────────────────────────────
public class GopExecutionLockDTO
{
public int ClientId { get; set; }
public int ExecutionId { get; set; }
public string LockedBy { get; set; } = string.Empty;
public DateTime LockedAt { get; set; } = DateTime.UtcNow;
public DateTime ExpiresAt { get; set; }
}
// ── Transaction: Source File ──────────────────────────────────
public class GopSourceFileDTO
{
public int ClientId { get; set; }
public int FileId { get; set; }
public string SourceCode { get; set; } = string.Empty;
public string OriginalFileName { get; set; } = string.Empty;
public string? StoredFilePath { get; set; }
public long? FileSizeBytes { get; set; }
public string? MimeType { get; set; }
public string UploadedBy { get; set; } = string.Empty;
public DateTime UploadedAt { get; set; } = DateTime.UtcNow;
public string Status { get; set; } = "Uploaded";
public int? QueueId { get; set; }
}
// ── Internal: Mapping Step Item (parsed from MappingJson) ─────
public class GopMappingStepItem
{
[JsonProperty("order")]
public int Order { get; set; }
[JsonProperty("sourcePath")]
public string SourcePath { get; set; } = string.Empty;
[JsonProperty("targetPath")]
public string TargetPath { get; set; } = string.Empty;
[JsonProperty("transform")]
public string? Transform { get; set; }
}
// ── Dashboard ─────────────────────────────────────────────────
public class GopQueueDashboardDTO
{
public string Status { get; set; } = string.Empty;
public int QueueCount { get; set; }
}
// ── File Upload ───────────────────────────────────────────────
/// Overall result returned by the file-upload endpoint.
public class GopFileUploadResponseDTO
{
public int FileId { get; set; }
public string FileName { get; set; } = string.Empty;
public string SourceType { get; set; } = string.Empty;
public int TotalRecords { get; set; }
public int SubmittedCount { get; set; }
public int FailedCount { get; set; }
public string Status { get; set; } = string.Empty; // Queued | PartialFailed | Failed
public List Results { get; set; } = new();
}
/// Per-row submission result inside a file upload response.
public class GopFileUploadItemResultDTO
{
public int RowIndex { get; set; }
public int? QueueId { get; set; }
public int? ExecutionId { get; set; }
public string Status { get; set; } = string.Empty; // Queued | Failed
public string? Error { get; set; }
}
}