namespace GB5Shared.DTO.PubSub { /// /// Rich event wrapper published to Dapr pubsub. /// Carries TOUTBOX metadata (EventTypeId, TenantId, ObjectId) alongside /// the entity payload so EventSub subscribers can identify the event and /// resolve the correct MACTION rows without an extra DB lookup. /// Published by OutBox.PublishPendingEventsAsync on topic "EVENTTYPEID:{id}". /// public class OutboxEventMessage { /// FK to MEVENTTYPE — identifies what happened. public int EventTypeId { get; set; } /// FK to entity type (ENTITYID on MEVENTTYPE). public int ObjectTypeId { get; set; } /// PK of the saved entity (e.g. TaskId). public int ObjectId { get; set; } /// Tenant that owns the event (TOUTBOX.TENANTID). public int TenantId { get; set; } /// UserId who triggered the original business event (TOUTBOX.USERID). public int UserId { get; set; } /// Serialised entity DTO (TOUTBOX.PAYLOAD). public string Payload { get; set; } = "{}"; /// Correlation key from TOUTBOX — links all downstream rows to the originating outbox event. public string CorrelationKey { get; set; } = string.Empty; /// /// The MSERVER connection name (LoginDTO.ConnectionDatabaseName) used by the publisher. /// Carried in the message so the framework subscriber can connect to the exact same /// tenant database without re-deriving it from MSERVERCONFIG — which can have multiple /// active records for the same ClientId and return the wrong database. /// When set, EventSubBLL uses this directly and skips the MSERVERCONFIG lookup entirely. /// public string ConnectionName { get; set; } = string.Empty; /// /// JSON-serialized array of . /// Set by BLL on UPDATE operations only; null for INSERT (full snapshot is in TEVENTLOG.DATA). /// EventLogSubBLL deserializes this and writes individual rows to TEVENTLOGCHANGE. /// Example: [{"FieldName":"Amount","OldValue":"1000","NewValue":"5000"}] /// public string? Changes { get; set; } /// GUID of the originating header row (TOUTBOX.HEADERROWGUID). Nullable. public Guid? HeaderRowGuid { get; set; } /// /// Full LoginDTO serialised as JSON — carries the complete session context of the user /// who triggered the event (WorkOUId, RoleId, BranchId, timezone, formats, etc.). /// Populated by BaseEntityAppService.ExecuteSaveAsync on the direct Dapr publish path. /// Defaults to "{}" on the outbox background-retry path where login state is /// unavailable; subscribers must handle both forms gracefully. /// WipApprovalId and RequestUrl are server-side-only and are excluded by [JsonIgnore]. /// public string LoginJson { get; set; } = "{}"; /// /// Pipeline context serialised as JSON — carries EntityId, ObjectId, EventTypeId, /// caller-supplied Facts (e.g. ParentTaskId, WIP bypass flag), and the DB_ENRICH bag /// values written by qualifier rules (e.g. ReportingToEmployeeId, DepartmentId). /// Also includes WorkflowInfo (mode, id, config) resolved during the save pipeline. /// Populated by BaseEntityAppService.ExecuteSaveAsync on the direct Dapr publish path. /// Defaults to a minimal JSON object on the outbox background-retry path. /// public string ContextJson { get; set; } = "{}"; /// /// W3C traceparent of the publisher's span (direct-publish or outbox-relay /// producer activity). Carried in the message body itself — rather than relying on /// Dapr/broker-level metadata propagation, which varies by pubsub component and /// CloudEvent wrapping mode — so EventActionSubscribeController can always /// reconstruct the correct parent via /// DaprEventTracing.StartSubscribeActivity and Zipkin/Jaeger stitch the /// publish → subscribe spans together across the service boundary. /// public string? TraceParent { get; set; } /// W3C tracestate accompanying , if any. public string? TraceState { get; set; } } }