diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ApiException.cs b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ApiException.cs deleted file mode 100644 index 7e88849..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ApiException.cs +++ /dev/null @@ -1,32 +0,0 @@ -using DigitalData.TaskFlow.Domain.Enums; - -namespace DigitalData.TaskFlow.Application.Common.Exceptions; - -/// -/// Represents an API-facing exception that carries HTTP and domain meta information. -/// -public class ApiException : Exception -{ - /// - /// Initializes a new instance of the class. - /// - /// HTTP status code to return. - /// Domain meta code to return. - /// Response message. - public ApiException(int statusCode, MetaCode metaCode, string message) - : base(message) - { - StatusCode = statusCode; - MetaCode = metaCode; - } - - /// - /// Gets the HTTP status code. - /// - public int StatusCode { get; } - - /// - /// Gets the domain meta code. - /// - public MetaCode MetaCode { get; } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ConflictApiException.cs b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ConflictApiException.cs deleted file mode 100644 index 937e56d..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ConflictApiException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using DigitalData.TaskFlow.Domain.Enums; - -namespace DigitalData.TaskFlow.Application.Common.Exceptions; - -/// -/// Represents a 409 API exception. -/// -public sealed class ConflictApiException : ApiException -{ - /// - /// Initializes a new instance of the class. - /// - /// Domain meta code to return. - /// Response message. - public ConflictApiException(MetaCode metaCode, string message) - : base(409, metaCode, message) - { - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ForbiddenApiException.cs b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ForbiddenApiException.cs deleted file mode 100644 index 09ae1bd..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/ForbiddenApiException.cs +++ /dev/null @@ -1,18 +0,0 @@ -using DigitalData.TaskFlow.Domain.Enums; - -namespace DigitalData.TaskFlow.Application.Common.Exceptions; - -/// -/// Represents a 403 API exception. -/// -public sealed class ForbiddenApiException : ApiException -{ - /// - /// Initializes a new instance of the class. - /// - /// Response message. - public ForbiddenApiException(string message) - : base(403, MetaCode.NoAccess, message) - { - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/InvalidRequestApiException.cs b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/InvalidRequestApiException.cs deleted file mode 100644 index d93772c..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/InvalidRequestApiException.cs +++ /dev/null @@ -1,18 +0,0 @@ -using DigitalData.TaskFlow.Domain.Enums; - -namespace DigitalData.TaskFlow.Application.Common.Exceptions; - -/// -/// Represents a 400 API exception. -/// -public sealed class InvalidRequestApiException : ApiException -{ - /// - /// Initializes a new instance of the class. - /// - /// Response message. - public InvalidRequestApiException(string message) - : base(400, MetaCode.InvalidRequest, message) - { - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/InvalidWorkflowPayloadException.cs b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/InvalidWorkflowPayloadException.cs new file mode 100644 index 0000000..1e161ea --- /dev/null +++ b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/InvalidWorkflowPayloadException.cs @@ -0,0 +1,5 @@ +namespace DigitalData.TaskFlow.Application.Common.Exceptions; + +public sealed class InvalidWorkflowPayloadException(string message) : Exception(message) +{ +} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/NotFoundApiException.cs b/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/NotFoundApiException.cs deleted file mode 100644 index bbc75c7..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Exceptions/NotFoundApiException.cs +++ /dev/null @@ -1,18 +0,0 @@ -using DigitalData.TaskFlow.Domain.Enums; - -namespace DigitalData.TaskFlow.Application.Common.Exceptions; - -/// -/// Represents a 404 API exception. -/// -public sealed class NotFoundApiException : ApiException -{ - /// - /// Initializes a new instance of the class. - /// - /// Response message. - public NotFoundApiException(string message) - : base(404, MetaCode.NotFound, message) - { - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Factories/ApiEnvelopeFactory.cs b/src/core/DigitalData.TaskFlow.Application/Common/Factories/ApiEnvelopeFactory.cs deleted file mode 100644 index 362fa90..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Factories/ApiEnvelopeFactory.cs +++ /dev/null @@ -1,49 +0,0 @@ -using DigitalData.TaskFlow.Domain.Common; -using DigitalData.TaskFlow.Domain.Enums; - -namespace DigitalData.TaskFlow.Application.Common.Factories; - -/// -/// Creates standard API envelope instances with centralized meta code/message handling. -/// -public static class ApiEnvelopeFactory -{ - /// - /// Creates a successful or business-result response envelope. - /// - /// Payload type. - /// Payload data. - /// Business result code. - /// Optional custom message. If not supplied, a default message is resolved from . - /// Response envelope containing meta and payload. - public static ApiEnvelope Create(T data, MetaCode code = MetaCode.Ok, string? message = null) - { - return new ApiEnvelope - { - Meta = - [ - new MetaEntry - { - Code = (int)code, - Message = message ?? ResolveDefaultMessage(code) - } - ], - Data = data - }; - } - - private static string ResolveDefaultMessage(MetaCode code) - { - return code switch - { - MetaCode.Ok => "OK", - MetaCode.NoOpenWorkflows => "Keine offenen Workflows", - MetaCode.NoAccess => "Kein Zugriff", - MetaCode.InvalidRequest => "Ungultiger Request", - MetaCode.InternalError => "Interner Fehler", - MetaCode.NotFound => "Vorgang nicht gefunden", - MetaCode.AlreadyClosed => "Vorgang bereits abgeschlossen", - _ => "Interner Fehler" - }; - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IDocumentRepository.cs b/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IDocumentRepository.cs index c42220e..2a52fa1 100644 --- a/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IDocumentRepository.cs +++ b/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IDocumentRepository.cs @@ -1,17 +1,13 @@ -using DigitalData.TaskFlow.Domain.Documents; +using DigitalData.TaskFlow.Domain.ProcedureResults; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace DigitalData.TaskFlow.Application.Common.Interfaces; -/// -/// Defines document-specific data access operations. -/// -public interface IDocumentRepository : IRepository +public interface IDocumentRepository { - /// - /// Gets document binary content for the given document identifier. - /// - /// Document identifier. - /// Cancellation token. - /// Binary document payload when found; otherwise . - Task GetAsync(string id, CancellationToken cancellationToken); + Task GetAsync(int userId, long processId, long docId, CancellationToken cancellationToken); } diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IWorkflowRepository.cs b/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IWorkflowRepository.cs index 87fb6ec..5f122a3 100644 --- a/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IWorkflowRepository.cs +++ b/src/core/DigitalData.TaskFlow.Application/Common/Interfaces/IWorkflowRepository.cs @@ -1,5 +1,4 @@ -using DigitalData.TaskFlow.Domain.Closing; -using DigitalData.TaskFlow.Domain.Workflows; +using DigitalData.TaskFlow.Domain.ProcedureResults; namespace DigitalData.TaskFlow.Application.Common.Interfaces; @@ -14,21 +13,5 @@ public interface IWorkflowRepository : IRepository /// WISAG user identifier. /// Cancellation token. /// Workflow data grouped by source. - Task GetAsync(int wisagId, CancellationToken cancellationToken); - - /// - /// Applies a closing decision to a workflow process. - /// - /// WISAG user identifier. - /// Source system name. - /// Process identifier. - /// Closing decision payload. - /// Cancellation token. - /// Closing operation result. - Task CloseAsync( - int wisagId, - string source, - int processId, - CloseWorkflowDecision decision, - CancellationToken cancellationToken); + Task GetByWisagIdAsync(int wisagId, CancellationToken cancellationToken); } diff --git a/src/core/DigitalData.TaskFlow.Application/Common/Mappings/ApplicationMappingProfile.cs b/src/core/DigitalData.TaskFlow.Application/Common/Mappings/ApplicationMappingProfile.cs deleted file mode 100644 index b9ed651..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Common/Mappings/ApplicationMappingProfile.cs +++ /dev/null @@ -1,19 +0,0 @@ -using AutoMapper; -using DigitalData.TaskFlow.Application.Features.Workflows.Commands.CloseWorkflow; -using DigitalData.TaskFlow.Domain.Closing; - -namespace DigitalData.TaskFlow.Application.Common.Mappings; - -/// -/// Defines AutoMapper configuration for application-level mappings. -/// -public sealed class ApplicationMappingProfile : Profile -{ - /// - /// Initializes mapping configuration. - /// - public ApplicationMappingProfile() - { - CreateMap(); - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/DependencyInjection.cs b/src/core/DigitalData.TaskFlow.Application/DependencyInjection.cs index 59c36d5..4f34d51 100644 --- a/src/core/DigitalData.TaskFlow.Application/DependencyInjection.cs +++ b/src/core/DigitalData.TaskFlow.Application/DependencyInjection.cs @@ -1,5 +1,4 @@ -using DigitalData.TaskFlow.Application.Options; -using FluentValidation; +using FluentValidation; using MediatR; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -10,29 +9,30 @@ namespace DigitalData.TaskFlow.Application; public static class DependencyInjection { + public const string LuckyPennySoftLicenseKeySection = "LuckyPennySoftLicenseKey"; + public static IServiceCollection AddApplicationServices(this IServiceCollection services, IConfiguration configuration) { - var mediatROptions = configuration - .GetSection(MediatROptions.SectionName) - .Get(); + var lpSoftLicenseKey = configuration[LuckyPennySoftLicenseKeySection]; + var hasLpSoftLicenseKey = !string.IsNullOrWhiteSpace(lpSoftLicenseKey); - services - .AddOptions() - .Bind(configuration.GetSection(MediatROptions.SectionName)); + var assembly = Assembly.GetExecutingAssembly(); services.AddMediatR(config => { - config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly); + config.RegisterServicesFromAssembly(assembly); - if (!string.IsNullOrWhiteSpace(mediatROptions?.LuckyPennySoftLicenseKey)) - { - config.LicenseKey = mediatROptions.LuckyPennySoftLicenseKey; - } + if (hasLpSoftLicenseKey) + config.LicenseKey = lpSoftLicenseKey; }); - services.AddValidatorsFromAssembly(typeof(DependencyInjection).Assembly); + services.AddValidatorsFromAssembly(assembly); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); - services.AddAutoMapper(_ => { }, Assembly.GetExecutingAssembly()); + services.AddAutoMapper(config => + { + if (hasLpSoftLicenseKey) + config.LicenseKey = lpSoftLicenseKey; + }, assembly); return services; } diff --git a/src/core/DigitalData.TaskFlow.Application/Features/Documents/Queries/GetDocument/GetDocumentQuery.cs b/src/core/DigitalData.TaskFlow.Application/Features/Documents/Queries/GetDocument/GetDocumentQuery.cs deleted file mode 100644 index b48c961..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Features/Documents/Queries/GetDocument/GetDocumentQuery.cs +++ /dev/null @@ -1,56 +0,0 @@ -using DigitalData.TaskFlow.Application.Common.Factories; -using DigitalData.TaskFlow.Application.Common.Exceptions; -using DigitalData.TaskFlow.Application.Common.Interfaces; -using DigitalData.TaskFlow.Domain.Common; -using DigitalData.TaskFlow.Domain.Documents; -using DigitalData.TaskFlow.Domain.Enums; -using FluentValidation; -using MediatR; - -namespace DigitalData.TaskFlow.Application.Features.Documents.Queries.GetDocument; - -/// -/// Represents a request to retrieve binary document content by document identifier. -/// -/// Document identifier. -public sealed record GetDocumentQuery(string Id) : IRequest>; - -/// -/// Validates requests. -/// -public sealed class GetDocumentQueryValidator : AbstractValidator -{ - /// - /// Initializes validation rules for . - /// - public GetDocumentQueryValidator() - { - RuleFor(x => x.Id) - .NotEmpty(); - } -} - -/// -/// Handles requests. -/// -public sealed class GetDocumentQueryHandler(IDocumentRepository documentRepository) - : IRequestHandler> -{ - /// - /// Executes the query and returns binary document data in the standard API envelope. - /// - /// Query request. - /// Cancellation token. - /// Document response envelope. - public async Task> Handle(GetDocumentQuery request, CancellationToken cancellationToken) - { - var document = await documentRepository.GetAsync(request.Id, cancellationToken); - - if (document is null) - { - throw new NotFoundApiException("Dokument nicht gefunden"); - } - - return ApiEnvelopeFactory.Create(document); - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Features/Documents/Queries/GetDocumentQuery.cs b/src/core/DigitalData.TaskFlow.Application/Features/Documents/Queries/GetDocumentQuery.cs new file mode 100644 index 0000000..c4c11c3 --- /dev/null +++ b/src/core/DigitalData.TaskFlow.Application/Features/Documents/Queries/GetDocumentQuery.cs @@ -0,0 +1,37 @@ +using DigitalData.TaskFlow.Application.Common.Exceptions; +using DigitalData.TaskFlow.Application.Common.Interfaces; +using MediatR; +using System.Text.Json; + +namespace DigitalData.TaskFlow.Application.Features.Documents.Queries; + +/// +/// +/// +/// +/// +/// +public sealed record GetDocumentQuery(int UserId, long ProcessId, long Id) : IRequest; + +public sealed class GetDocumentQueryHandler(IDocumentRepository Repo) : IRequestHandler +{ + public async Task Handle(GetDocumentQuery request, CancellationToken cancellationToken) + { + var document = await Repo.GetAsync(userId: request.UserId, processId: request.ProcessId, docId: request.Id, cancellationToken); + + if (!string.IsNullOrWhiteSpace(document?.Result)) + { + using var doc = JsonDocument.Parse(document.Result); + var root = doc.RootElement; + + if (root.ValueKind == JsonValueKind.Object && + root.TryGetProperty("response", out var response)) + { + return response.Clone(); + } + } + + throw new InvalidWorkflowPayloadException( + "Stored procedure returned an invalid payload. Expected a JSON object with a 'response' property."); + } +} diff --git a/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Commands/CloseWorkflow/CloseWorkflowCommand.cs b/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Commands/CloseWorkflow/CloseWorkflowCommand.cs deleted file mode 100644 index bc2e451..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Commands/CloseWorkflow/CloseWorkflowCommand.cs +++ /dev/null @@ -1,126 +0,0 @@ -using DigitalData.TaskFlow.Application.Common.Exceptions; -using DigitalData.TaskFlow.Application.Common.Interfaces; -using DigitalData.TaskFlow.Application.Common.Factories; -using AutoMapper; -using DigitalData.TaskFlow.Domain.Closing; -using DigitalData.TaskFlow.Domain.Common; -using DigitalData.TaskFlow.Domain.Enums; -using FluentValidation; -using MediatR; - -namespace DigitalData.TaskFlow.Application.Features.Workflows.Commands.CloseWorkflow; - -/// -/// Represents a request to close a workflow process using a selected closing method. -/// -/// WISAG user identifier. -/// Source system name. -/// Process identifier. -/// Selected closing method identifier. -/// Optional user comment. -/// Optional rejection reason identifier. -public sealed record CloseWorkflowCommand( - int WisagId, - string Source, - int ProcessId, - int ClosingMethodId, - string? Comment, - int? RejectionReasonId) - : IRequest>; - -/// -/// Validates requests. -/// -public sealed class CloseWorkflowCommandValidator : AbstractValidator -{ - private static readonly string[] AllowedSources = ["Ferdinand", "Contracts"]; - private const int ApproveMethodId = 2; - private const int RejectMethodId = 3; - private const int BackToPerMethodId = 4; - - /// - /// Initializes validation rules for . - /// - public CloseWorkflowCommandValidator() - { - RuleFor(x => x.WisagId) - .GreaterThan(0); - - RuleFor(x => x.ProcessId) - .GreaterThan(0); - - RuleFor(x => x.ClosingMethodId) - .GreaterThan(0); - - RuleFor(x => x.Source) - .NotEmpty() - .Must(source => AllowedSources.Contains(source)) - .WithMessage("Source must be one of the supported source systems."); - - RuleFor(x => x.ClosingMethodId) - .Must(methodId => methodId is ApproveMethodId or RejectMethodId or BackToPerMethodId) - .WithMessage("Unbekannte closing_method_id"); - - RuleFor(x => x.Comment) - .NotEmpty() - .When(x => x.ClosingMethodId is RejectMethodId or BackToPerMethodId) - .WithMessage("Kommentar ist fur diese closing_method Pflicht"); - - RuleFor(x => x.RejectionReasonId) - .NotNull() - .When(x => x.ClosingMethodId == RejectMethodId) - .WithMessage("rejection_reason_id ist fur diese closing_method Pflicht"); - } -} - -/// -/// Handles requests. -/// -public sealed class CloseWorkflowCommandHandler(IWorkflowRepository workflowRepository, IMapper mapper) - : IRequestHandler> -{ - /// - /// Executes the closing request and returns the operation result in the standard API envelope. - /// - /// Command request. - /// Cancellation token. - /// Closing result envelope. - public async Task> Handle(CloseWorkflowCommand request, CancellationToken cancellationToken) - { - if (string.Equals(request.Source, "Contracts", StringComparison.OrdinalIgnoreCase)) - { - throw new InvalidRequestApiException("Quelle 'Contracts' wird fur Closing aktuell nicht unterstutzt"); - } - - var decision = mapper.Map(request); - - var result = await workflowRepository.CloseAsync( - request.WisagId, - request.Source, - request.ProcessId, - decision, - cancellationToken); - - if (result.Outcome == CloseWorkflowOutcome.NoAccess) - { - throw new ForbiddenApiException("Kein Zugriff"); - } - - if (result.Outcome == CloseWorkflowOutcome.NotImplemented) - { - throw new InvalidOperationException("Closing integration is not finalized yet."); - } - - if (result.ProcessId <= 0) - { - throw new NotFoundApiException("Vorgang nicht gefunden"); - } - - if (!result.IsClosed) - { - throw new ConflictApiException(MetaCode.AlreadyClosed, "Vorgang bereits abgeschlossen"); - } - - return ApiEnvelopeFactory.Create(result); - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Queries/GetWorkflows/GetWorkflowsQuery.cs b/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Queries/GetWorkflows/GetWorkflowsQuery.cs deleted file mode 100644 index 271bc88..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Queries/GetWorkflows/GetWorkflowsQuery.cs +++ /dev/null @@ -1,67 +0,0 @@ -using DigitalData.TaskFlow.Application.Common.Factories; -using DigitalData.TaskFlow.Application.Common.Interfaces; -using DigitalData.TaskFlow.Domain.Common; -using DigitalData.TaskFlow.Domain.Enums; -using DigitalData.TaskFlow.Domain.Workflows; -using FluentValidation; -using MediatR; - -namespace DigitalData.TaskFlow.Application.Features.Workflows.Queries.GetWorkflows; - -/// -/// Represents a request to fetch grouped workflow data for a WISAG user. -/// -/// WISAG user identifier. -public sealed record GetWorkflowsQuery(int WisagId) : IRequest>; - -/// -/// Validates requests. -/// -public sealed class GetWorkflowsQueryValidator : AbstractValidator -{ - /// - /// Initializes validation rules for . - /// - public GetWorkflowsQueryValidator() - { - RuleFor(x => x.WisagId) - .GreaterThan(0); - } -} - -/// -/// Handles requests. -/// -public sealed class GetWorkflowsQueryHandler(IWorkflowRepository workflowRepository) - : IRequestHandler> -{ - /// - /// Executes the query and returns a workflow payload wrapped in the standard API envelope. - /// - /// Query request. - /// Cancellation token. - /// Workflow response envelope. - public async Task> Handle(GetWorkflowsQuery request, CancellationToken cancellationToken) - { - var data = await workflowRepository.GetAsync(request.WisagId, cancellationToken); - - if (data.Sources.Count == 0) - { - return ApiEnvelopeFactory.Create(data, MetaCode.NoAccess); - } - - var hasListingData = data.Sources.Any(source => source switch - { - FerdinandSourceBlock ferdinand => ferdinand.Listing.Count > 0, - ContractsSourceBlock contracts => contracts.Listing.Count > 0, - _ => false - }); - - if (!hasListingData) - { - return ApiEnvelopeFactory.Create(data, MetaCode.NoOpenWorkflows); - } - - return ApiEnvelopeFactory.Create(data); - } -} diff --git a/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Queries/GetWorkflowsQuery.cs b/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Queries/GetWorkflowsQuery.cs new file mode 100644 index 0000000..890485e --- /dev/null +++ b/src/core/DigitalData.TaskFlow.Application/Features/Workflows/Queries/GetWorkflowsQuery.cs @@ -0,0 +1,35 @@ +using DigitalData.TaskFlow.Application.Common.Exceptions; +using DigitalData.TaskFlow.Application.Common.Interfaces; +using MediatR; +using System.Text.Json; + +namespace DigitalData.TaskFlow.Application.Features.Workflows.Queries; + +/// +/// Represents a request to fetch grouped workflow data for a WISAG user. +/// +/// WISAG user identifier. +public sealed record GetWorkflowsQuery(int WisagId) : IRequest; + +public sealed class GetWorkflowsQueryHandler(IWorkflowRepository Repo) : IRequestHandler +{ + public async Task Handle(GetWorkflowsQuery request, CancellationToken cancellationToken) + { + var workflow = await Repo.GetByWisagIdAsync(request.WisagId, cancellationToken); + + if (!string.IsNullOrWhiteSpace(workflow?.Result)) + { + using var document = JsonDocument.Parse(workflow.Result); + var root = document.RootElement; + + if (root.ValueKind == JsonValueKind.Object && + root.TryGetProperty("response", out var response)) + { + return response.Clone(); + } + } + + throw new InvalidWorkflowPayloadException( + "Stored procedure returned an invalid payload. Expected a JSON object with a 'response' property."); + } +} diff --git a/src/core/DigitalData.TaskFlow.Application/Options/MediatROptions.cs b/src/core/DigitalData.TaskFlow.Application/Options/MediatROptions.cs deleted file mode 100644 index a11efff..0000000 --- a/src/core/DigitalData.TaskFlow.Application/Options/MediatROptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace DigitalData.TaskFlow.Application.Options; - -public sealed class MediatROptions -{ - public const string SectionName = "MediatR"; - - public string? LuckyPennySoftLicenseKey { get; init; } -} diff --git a/src/core/DigitalData.TaskFlow.Application/README.md b/src/core/DigitalData.TaskFlow.Application/README.md deleted file mode 100644 index d57e531..0000000 --- a/src/core/DigitalData.TaskFlow.Application/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# DigitalData.TaskFlow.Application - -Dieses Projekt enthaelt die Use-Case-Schicht der Anwendung. - -## Zweck - -Die Application-Schicht orchestriert fachliche Anwendungsfaelle. Sie nimmt Requests entgegen, validiert diese, ruft Domain-nahe Abstraktionen auf und liefert strukturierte Ergebnisse zurueck. - -## Aktueller Inhalt - -- `DependencyInjection.cs` - - Registriert zentrale Application-Dienste: - - MediatR - - FluentValidation - - AutoMapper - - Bindet `MediatR`-Optionen inklusive Lizenzschluessel. -- `Options/` - - `MediatROptions`: Konfiguration fuer MediatR (z. B. `LuckyPennySoftLicenseKey`). - -## Geplante Inhalte (naechste Phasen) - -- `Features/` - - Queries/Commands fuer Workflows, Closing und Documents. -- `Validators/` - - FluentValidation-Regeln pro Request. -- `Common/Behaviors/` - - Pipeline-Behavior (z. B. zentrale Request-Validierung). -- `Common/Interfaces/` - - Repository-Abstraktionen fuer Datenzugriff. -- `Mappings/` - - AutoMapper-Profile zwischen Infrastrukturmodellen und Domainmodellen. - -## Architektur-Regeln - -- Keine direkten SQL- oder EF-Core-Aufrufe. -- Keine HTTP-spezifischen Controller-Abhaengigkeiten. -- Kommunikation nach aussen nur ueber Interfaces. - -## Rolle im Gesamtsystem - -Diese Schicht ist der zentrale Ausfuehrungspunkt fuer Use-Cases und verbindet die API-Schicht mit Domain und Infrastructure, ohne Technologie-Details nach oben durchzureichen.