refactor(domain): replace workflow aggregates with procedure results
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Closing;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the user decision payload for closing a workflow process.
|
||||
/// </summary>
|
||||
public sealed record CloseWorkflowDecision
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the selected closing method identifier.
|
||||
/// </summary>
|
||||
public required int ClosingMethodId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional comment attached to the decision.
|
||||
/// </summary>
|
||||
public string? Comment { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional rejection reason identifier.
|
||||
/// </summary>
|
||||
public int? RejectionReasonId { get; init; }
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Closing;
|
||||
|
||||
/// <summary>
|
||||
/// Defines business outcomes of a close workflow attempt.
|
||||
/// </summary>
|
||||
public enum CloseWorkflowOutcome
|
||||
{
|
||||
/// <summary>
|
||||
/// Workflow can be closed successfully.
|
||||
/// </summary>
|
||||
Closed = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Caller has no access to the requested workflow.
|
||||
/// </summary>
|
||||
NoAccess = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Workflow process was not found.
|
||||
/// </summary>
|
||||
NotFound = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Workflow is already closed and cannot be closed again.
|
||||
/// </summary>
|
||||
AlreadyClosed = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Closing cannot be completed yet because write integration is not finalized.
|
||||
/// </summary>
|
||||
NotImplemented = 4
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Closing;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the result of a workflow closing operation.
|
||||
/// </summary>
|
||||
public sealed record CloseWorkflowResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the process identifier.
|
||||
/// </summary>
|
||||
public required int ProcessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the process was closed successfully.
|
||||
/// </summary>
|
||||
public required bool IsClosed { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the business outcome of the close request.
|
||||
/// </summary>
|
||||
public CloseWorkflowOutcome Outcome { get; init; } = CloseWorkflowOutcome.Closed;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the standard API envelope that contains meta information and payload data.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the payload in the response.</typeparam>
|
||||
public sealed record ApiEnvelope<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the list of metadata entries describing the business result.
|
||||
/// </summary>
|
||||
public required IReadOnlyList<MetaEntry> Meta { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the payload data returned by the endpoint.
|
||||
/// </summary>
|
||||
public T? Data { get; init; }
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single metadata item describing the business result state of an API response.
|
||||
/// </summary>
|
||||
public sealed record MetaEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the domain-specific result code.
|
||||
/// </summary>
|
||||
public required int Code { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the human-readable message that belongs to <see cref="Code"/>.
|
||||
/// </summary>
|
||||
public required string Message { get; init; }
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Documents;
|
||||
|
||||
/// <summary>
|
||||
/// Represents binary document content returned by the document endpoint.
|
||||
/// </summary>
|
||||
public sealed record DocumentBinaryResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the raw binary content.
|
||||
/// </summary>
|
||||
public required byte[] Content { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MIME content type.
|
||||
/// </summary>
|
||||
public required string ContentType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file name used for download.
|
||||
/// </summary>
|
||||
public required string FileName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content length in bytes.
|
||||
/// </summary>
|
||||
public required long Length { get; init; }
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace DigitalData.TaskFlow.Domain.Entities;
|
||||
|
||||
[Table("TBCUST_DOC_BASE64", Schema = "dbo")]
|
||||
public sealed class CustDocBase64
|
||||
{
|
||||
[Column("ProcessID", TypeName = "bigint")]
|
||||
public long? ProcessId { get; set; }
|
||||
|
||||
[Column("DocID", TypeName = "bigint")]
|
||||
public long? DocId { get; set; }
|
||||
|
||||
[Column("Doctype", TypeName = "nvarchar(200)")]
|
||||
public string? DocType { get; set; }
|
||||
|
||||
[Column("GroupType", TypeName = "nvarchar(200)")]
|
||||
public string? GroupType { get; set; }
|
||||
|
||||
[Column("filename", TypeName = "nvarchar(500)")]
|
||||
public string? FileName { get; set; }
|
||||
|
||||
[Column("filebase64", TypeName = "varchar(max)")]
|
||||
public string? FileBase64 { get; set; }
|
||||
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
[Column("thumbnailbase64", TypeName = "varchar(max)")]
|
||||
public string? ThumbnailBase64 { get; set; }
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Defines domain-level result codes used in API meta responses.
|
||||
/// </summary>
|
||||
public enum MetaCode
|
||||
{
|
||||
/// <summary>
|
||||
/// Operation completed successfully.
|
||||
/// </summary>
|
||||
Ok = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Request is valid but no open workflows are available.
|
||||
/// </summary>
|
||||
NoOpenWorkflows = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Caller has no access to the requested resource.
|
||||
/// </summary>
|
||||
NoAccess = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Request is invalid or authentication failed according to endpoint rules.
|
||||
/// </summary>
|
||||
InvalidRequest = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Internal server error occurred.
|
||||
/// </summary>
|
||||
InternalError = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Requested resource was not found.
|
||||
/// </summary>
|
||||
NotFound = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Target workflow was already closed.
|
||||
/// </summary>
|
||||
AlreadyClosed = 7
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace DigitalData.TaskFlow.Domain.ProcedureResults;
|
||||
|
||||
public class Document : ProcedureResultBase
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace DigitalData.TaskFlow.Domain.ProcedureResults;
|
||||
|
||||
public abstract class ProcedureResultBase
|
||||
{
|
||||
public virtual int? Code { get; init; }
|
||||
|
||||
public virtual string? Result { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace DigitalData.TaskFlow.Domain.ProcedureResults;
|
||||
|
||||
public class Workflow : ProcedureResultBase
|
||||
{
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
# DigitalData.TaskFlow.Domain
|
||||
|
||||
Dieses Projekt bildet den fachlichen Kern von `DigitalData.TaskFlow`.
|
||||
|
||||
## Zweck
|
||||
|
||||
Die Domain-Schicht enthaelt ausschließlich fachliche Modelle und Begriffe. Hier wird beschrieben, **was** das System fachlich darstellt, nicht **wie** Daten gelesen/geschrieben werden.
|
||||
|
||||
## Aktueller Inhalt
|
||||
|
||||
- `Common/`
|
||||
- `ApiEnvelope<T>`: Standard-Response-Huelle mit `Meta` und `Data`.
|
||||
- `MetaEntry`: Einzelner Meta-Eintrag (`Code`, `Message`).
|
||||
- `Enums/`
|
||||
- `MetaCode`: Fachliche Status-Codes (z. B. `Ok`, `NoAccess`, `AlreadyClosed`).
|
||||
- `Workflows/`
|
||||
- Modelle fuer den Endpoint `GET /workflows/{wisagid}`.
|
||||
- Enthalten Quellblock-Struktur (`SourceBlock`, `FerdinandSourceBlock`, `ContractsSourceBlock`) und Untermodelle (`ProfileItem`, `WorkflowListingItem`, `ApprovalItem`, `DocumentReferenceItem`, `ClosingMethodItem`, `RejectionReasonItem`).
|
||||
- `Closing/`
|
||||
- Modelle fuer den Endpoint `POST /workflows/{wisagid}/{source}/{processid}/closing`.
|
||||
- `CloseWorkflowDecision` (Eingabe), `CloseWorkflowResult` (Ergebnis).
|
||||
- `Documents/`
|
||||
- `DocumentBinaryResult` fuer den Endpoint `GET /documents/{id}`.
|
||||
|
||||
## Architektur-Regeln
|
||||
|
||||
- Keine EF-Core-, HTTP-, SQL- oder Infrastruktur-Abhaengigkeiten.
|
||||
- Keine Controller- oder Middleware-Logik.
|
||||
- Modelle bleiben in PascalCase; technische DB-Namensabweichungen werden spaeter in Infrastructure gemappt.
|
||||
|
||||
## Warum diese Schicht wichtig ist
|
||||
|
||||
Die Domain stellt eine stabile, technologieunabhaengige Sprache bereit. Dadurch koennen API, Application und Infrastructure getrennt entwickelt werden, ohne den fachlichen Vertrag zu verlieren.
|
||||
@@ -1,32 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a completed approval action for a workflow process.
|
||||
/// </summary>
|
||||
public sealed record ApprovalItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the process identifier.
|
||||
/// </summary>
|
||||
public required int ProcessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the approval sequence index.
|
||||
/// </summary>
|
||||
public required int Sequence { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user name or identifier of the approver.
|
||||
/// </summary>
|
||||
public required string ApprovedBy { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UTC timestamp when approval was recorded.
|
||||
/// </summary>
|
||||
public required DateTime ApprovedAtUtc { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional approval comment.
|
||||
/// </summary>
|
||||
public string? Comment { get; init; }
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a workflow closing option available for user decision.
|
||||
/// </summary>
|
||||
public sealed record ClosingMethodItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the closing method identifier.
|
||||
/// </summary>
|
||||
public required int ClosingMethodId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display name of the method.
|
||||
/// </summary>
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a comment is mandatory for this method.
|
||||
/// </summary>
|
||||
public required bool CommentRequired { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this method represents a rejection.
|
||||
/// </summary>
|
||||
public required bool IsRejection { get; init; }
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// Represents workflow data for the Contracts source system.
|
||||
/// </summary>
|
||||
public sealed record ContractsSourceBlock : SourceBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets available approval profiles.
|
||||
/// </summary>
|
||||
[JsonPropertyName("profile")]
|
||||
public required IReadOnlyList<JsonElement> Profile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets workflow listing items.
|
||||
/// </summary>
|
||||
[JsonPropertyName("Listing")]
|
||||
public required IReadOnlyList<JsonElement> Listing { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets already executed approvals.
|
||||
/// </summary>
|
||||
[JsonPropertyName("approvals")]
|
||||
public required IReadOnlyList<JsonElement> Approvals { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets document references for workflows.
|
||||
/// </summary>
|
||||
[JsonPropertyName("document")]
|
||||
public required IReadOnlyList<JsonElement> Document { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets available closing methods for workflows.
|
||||
/// </summary>
|
||||
[JsonPropertyName("closing_method")]
|
||||
public required IReadOnlyList<JsonElement> ClosingMethod { get; init; }
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a lightweight document reference linked to a workflow process.
|
||||
/// </summary>
|
||||
public sealed record DocumentReferenceItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the document identifier used for binary retrieval.
|
||||
/// </summary>
|
||||
public required string Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the process identifier.
|
||||
/// </summary>
|
||||
public required int ProcessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the document title.
|
||||
/// </summary>
|
||||
public required string Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the document subtitle.
|
||||
/// </summary>
|
||||
public required string Subtitle { get; init; }
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// Represents workflow data for the Ferdinand source system.
|
||||
/// </summary>
|
||||
public sealed record FerdinandSourceBlock : SourceBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets available approval profiles.
|
||||
/// </summary>
|
||||
[JsonPropertyName("profile")]
|
||||
public required IReadOnlyList<JsonElement> Profile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets workflow listing items.
|
||||
/// </summary>
|
||||
[JsonPropertyName("Listing")]
|
||||
public required IReadOnlyList<JsonElement> Listing { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets already executed approvals.
|
||||
/// </summary>
|
||||
[JsonPropertyName("approvals")]
|
||||
public required IReadOnlyList<JsonElement> Approvals { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets document references for workflows.
|
||||
/// </summary>
|
||||
[JsonPropertyName("document")]
|
||||
public required IReadOnlyList<JsonElement> Document { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets available closing methods for workflows.
|
||||
/// </summary>
|
||||
[JsonPropertyName("closing_method")]
|
||||
public required IReadOnlyList<JsonElement> ClosingMethod { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets available rejection reasons for rejection-type methods.
|
||||
/// </summary>
|
||||
[JsonPropertyName("rejection_reason")]
|
||||
public required IReadOnlyList<JsonElement> RejectionReason { get; init; }
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an approval profile for workflow processing.
|
||||
/// </summary>
|
||||
public sealed record ProfileItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the profile identifier.
|
||||
/// </summary>
|
||||
public required int ProfileId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display title of the profile.
|
||||
/// </summary>
|
||||
public required string Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional priority value.
|
||||
/// </summary>
|
||||
public int? Priority { get; init; }
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rejection reason that can be selected for rejection methods.
|
||||
/// </summary>
|
||||
public sealed record RejectionReasonItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the rejection reason identifier.
|
||||
/// </summary>
|
||||
public required int RejectionReasonId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display name of the rejection reason.
|
||||
/// </summary>
|
||||
public required string Name { get; init; }
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Base type for source-specific workflow blocks.
|
||||
/// </summary>
|
||||
public abstract record SourceBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the source system name.
|
||||
/// </summary>
|
||||
public required string Source { get; init; }
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single workflow listing row.
|
||||
/// </summary>
|
||||
public sealed record WorkflowListingItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the process identifier.
|
||||
/// </summary>
|
||||
public required int ProcessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile identifier associated with the process.
|
||||
/// </summary>
|
||||
public required int ProfileId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the voucher type.
|
||||
/// </summary>
|
||||
public required string VoucherType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the voucher number.
|
||||
/// </summary>
|
||||
public required string VoucherNumber { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the voucher date.
|
||||
/// </summary>
|
||||
public required DateOnly VoucherDate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cost center number.
|
||||
/// </summary>
|
||||
public required string CostCenter { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cost center description.
|
||||
/// </summary>
|
||||
public required string CostCenterDescription { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the client number.
|
||||
/// </summary>
|
||||
public required int ClientNumber { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the client name.
|
||||
/// </summary>
|
||||
public required string ClientName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supplier number.
|
||||
/// </summary>
|
||||
public required string SupplierNumber { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supplier name.
|
||||
/// </summary>
|
||||
public required string SupplierName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the net amount.
|
||||
/// </summary>
|
||||
public required decimal NetAmount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gross amount.
|
||||
/// </summary>
|
||||
public required decimal GrossAmount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the discount amount.
|
||||
/// </summary>
|
||||
public required decimal DiscountAmount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currency.
|
||||
/// </summary>
|
||||
public required string Currency { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority value.
|
||||
/// </summary>
|
||||
public required int Priority { get; init; }
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace DigitalData.TaskFlow.Domain.Workflows;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the workflow payload grouped by source systems.
|
||||
/// </summary>
|
||||
public sealed record WorkflowSourcesResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the source blocks included in the response.
|
||||
/// </summary>
|
||||
public required IReadOnlyList<SourceBlock> Sources { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user