diff --git a/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommand.cs b/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommand.cs deleted file mode 100644 index cf35a5bb..00000000 --- a/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommand.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Cfo.Cats.Application.Features.Documents.Caching; -using Cfo.Cats.Application.Features.Documents.DTOs; -using Cfo.Cats.Domain.Entities.Documents; - -namespace Cfo.Cats.Application.Features.Documents.Commands.AddEdit; - -public class AddEditDocumentCommand : ICacheInvalidatorRequest> -{ - - [Description("Id")] - public Guid Id { get;set; } - - [Description("Title")] public string? Title { get; set; } - - [Description("Description")] public string? Description { get; set; } - - [Description("Is Public")] public bool IsPublic { get; set; } - - [Description("URL")] public string? URL { get; set; } - - [Description("Document Type")] public DocumentType DocumentType { get; set; } = DocumentType.Document; - - [Description("Tenant Id")] public string? TenantId { get; set; } - - [Description("Tenant Name")] public string? TenantName { get; set; } - - [Description("Content")] public string? Content { get; set; } - - public UploadRequest? UploadRequest { get; set; } - - public string CacheKey => DocumentCacheKey.GetDocumentCacheKey(Id); - public CancellationTokenSource? SharedExpiryTokenSource => DocumentCacheKey.SharedExpiryTokenSource(); - - private class Mapping : Profile - { - public Mapping() - { - CreateMap(MemberList.None); - CreateMap(MemberList.None); - } - } - -} \ No newline at end of file diff --git a/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommandHandler.cs b/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommandHandler.cs deleted file mode 100644 index c0c6240a..00000000 --- a/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ - -using Cfo.Cats.Domain.Entities.Documents; -using Cfo.Cats.Domain.Events; - -namespace Cfo.Cats.Application.Features.Documents.Commands.AddEdit; - -public class AddEditDocumentCommandHandler : IRequestHandler> -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - private readonly IUploadService _uploadService; - - public AddEditDocumentCommandHandler( - IApplicationDbContext context, - IMapper mapper, - IUploadService uploadService - ) - { - _context = context; - _mapper = mapper; - _uploadService = uploadService; - } - - public async Task> Handle(AddEditDocumentCommand request, CancellationToken cancellationToken) - { - if (request.Id != Guid.Empty) - { - var document = await _context.Documents.FindAsync(new object[] { request.Id }, cancellationToken); - _ = document ?? throw new NotFoundException($"Document {request.Id} Not Found."); - document.AddDomainEvent(new DocumentUpdatedDomainEvent(document)); - if (request.UploadRequest != null) - { - document.URL = await _uploadService.UploadAsync("", request.UploadRequest); - } - - document.Title = request.Title; - document.Description = request.Description; - document.IsPublic = request.IsPublic; - document.DocumentType = request.DocumentType; - await _context.SaveChangesAsync(cancellationToken); - return await Result.SuccessAsync(document.Id); - } - else - { - var document = _mapper.Map(request); - if (request.UploadRequest != null) - { - document.URL = await _uploadService.UploadAsync("", request.UploadRequest); - } - - document.AddDomainEvent(new DocumentCreatedDomainEvent(document)); - _context.Documents.Add(document); - await _context.SaveChangesAsync(cancellationToken); - return await Result.SuccessAsync(document.Id); - } - } -} \ No newline at end of file diff --git a/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommandValidator.cs b/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommandValidator.cs deleted file mode 100644 index 5198fef4..00000000 --- a/src/Application/Features/Documents/Commands/AddEdit/AddEditDocumentCommandValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Cfo.Cats.Application.Features.Documents.Commands.AddEdit; - -public class AddEditDocumentCommandValidator : AbstractValidator -{ - public AddEditDocumentCommandValidator() - { - RuleFor(v => v.Title) - .NotNull() - .MaximumLength(256) - .NotEmpty(); - RuleFor(v => v.DocumentType) - .NotNull(); - RuleFor(v => v.Description) - .MaximumLength(256); - RuleFor(v => v.UploadRequest) - .NotNull() - .When(x => x.Id == Guid.Empty); - } -} \ No newline at end of file diff --git a/src/Application/Features/Participants/Commands/AddConsent.cs b/src/Application/Features/Participants/Commands/AddConsent.cs index ff7e5908..29def248 100644 --- a/src/Application/Features/Participants/Commands/AddConsent.cs +++ b/src/Application/Features/Participants/Commands/AddConsent.cs @@ -31,17 +31,13 @@ public async Task> Handle(Command request, CancellationToken canc throw new NotFoundException("Cannot find participant", request.ParticipantId); } - var document = new Document() - { - Description = $"Consent form for {request.ParticipantId}", - DocumentType = DocumentType.Document, - IsPublic = false, - Title = request.UploadRequest!.FileName - }; + var document = Document.Create(request.UploadRequest!.FileName, + $"Consent form for {request.ParticipantId}", + DocumentType.PDF); var result = await uploadService.UploadAsync($"{request.ParticipantId}/consent", request.UploadRequest!); - document.URL = result; + document.SetURL(result); participant.AddConsent(request.ConsentDate!.Value, document.Id); diff --git a/src/Application/Features/Participants/Commands/AddRightToWork.cs b/src/Application/Features/Participants/Commands/AddRightToWork.cs index cb193430..b136f25a 100644 --- a/src/Application/Features/Participants/Commands/AddRightToWork.cs +++ b/src/Application/Features/Participants/Commands/AddRightToWork.cs @@ -33,17 +33,14 @@ public async Task> Handle(Command request, CancellationToken canc { throw new NotFoundException("Cannot find participant", request.ParticipantId); } + + var document = Document.Create(request.UploadRequest!.FileName, + $"Right to work evidence for {request.ParticipantId}", + DocumentType.PDF); - var document = new Document() - { - Description = $"Right to work evidence for {request.ParticipantId}", - DocumentType = DocumentType.Document, - IsPublic = false, - Title = request.UploadRequest!.FileName - }; var result = await uploadService.UploadAsync($"{request.ParticipantId}/rtw", request.UploadRequest!); - document.URL = result; + document.SetURL(result); participant.AddRightToWork(request.ValidFrom!.Value, request.ValidTo!.Value, document.Id); diff --git a/src/Domain/Entities/Documents/Document.cs b/src/Domain/Entities/Documents/Document.cs index b732cb23..95c948e3 100644 --- a/src/Domain/Entities/Documents/Document.cs +++ b/src/Domain/Entities/Documents/Document.cs @@ -1,25 +1,50 @@ using Cfo.Cats.Domain.Common.Contracts; using Cfo.Cats.Domain.Common.Entities; using Cfo.Cats.Domain.Entities.Administration; +using Cfo.Cats.Domain.Events; namespace Cfo.Cats.Domain.Entities.Documents; public class Document : OwnerPropertyEntity, IMayHaveTenant, IAuditTrial { - public Document() + private Document() { Id = Guid.NewGuid(); } - public string? Title { get; set; } - public string? Description { get; set; } - public string? Content { get; set; } - public bool IsPublic { get; set; } - public string? URL { get; set; } - public DocumentType DocumentType { get; set; } = default!; + private Document(string title, string description, DocumentType documentType) + { + Title = title; + IsPublic = false; + Description = description; + DocumentType = documentType; + + AddDomainEvent(new DocumentCreatedDomainEvent(this)); + } + + + public static Document Create(string title, string description, DocumentType documentType) + { + return new(title, description, documentType); + } + + public Document SetURL(string url) + { + URL = url; + return this; + } + + public string? Title { get; private set; } + public string? Description { get; private set; } + + [Obsolete("We are not storing the content with the document", false)] + public string? Content { get; private set; } + public bool IsPublic { get; private set; } + public string? URL { get; private set; } + public DocumentType DocumentType { get; private set; } = default!; public virtual Tenant? Tenant { get; set; } - public string? TenantId {get;set;} + public string? TenantId {get; set;} } public enum DocumentType diff --git a/src/Domain/Events/DocumentEvents.cs b/src/Domain/Events/DocumentEvents.cs index 61504d60..3fa84cde 100644 --- a/src/Domain/Events/DocumentEvents.cs +++ b/src/Domain/Events/DocumentEvents.cs @@ -3,6 +3,6 @@ namespace Cfo.Cats.Domain.Events; -public class DocumentCreatedDomainEvent(Document entity) : CreatedDomainEvent(entity); +public sealed class DocumentCreatedDomainEvent(Document entity) : CreatedDomainEvent(entity); -public class DocumentUpdatedDomainEvent(Document entity) : UpdatedDomainEvent(entity); \ No newline at end of file +public sealed class DocumentUpdatedDomainEvent(Document entity) : UpdatedDomainEvent(entity); \ No newline at end of file diff --git a/src/Domain/Events/RightToWorkEvents.cs b/src/Domain/Events/RightToWorkEvents.cs index e6a5860c..ae31bdf2 100644 --- a/src/Domain/Events/RightToWorkEvents.cs +++ b/src/Domain/Events/RightToWorkEvents.cs @@ -4,4 +4,4 @@ namespace Cfo.Cats.Domain.Events; -public class RightToWorkCreatedDomainEvent(RightToWork entity) : CreatedDomainEvent(entity); \ No newline at end of file +public sealed class RightToWorkCreatedDomainEvent(RightToWork entity) : CreatedDomainEvent(entity); \ No newline at end of file diff --git a/src/Domain/Events/TenantRenamedDomainEvent.cs b/src/Domain/Events/TenantRenamedDomainEvent.cs index 131e71d2..a2b8b429 100644 --- a/src/Domain/Events/TenantRenamedDomainEvent.cs +++ b/src/Domain/Events/TenantRenamedDomainEvent.cs @@ -3,7 +3,7 @@ namespace Cfo.Cats.Domain.Events; -public class TenantRenamedDomainEvent(Tenant entity, string oldName) : UpdatedDomainEvent(entity) +public sealed class TenantRenamedDomainEvent(Tenant entity, string oldName) : UpdatedDomainEvent(entity) { public string OldName { get; } = oldName; } diff --git a/test/Application.UnitTests/Mappings/MappingTests.cs b/test/Application.UnitTests/Mappings/MappingTests.cs index aea732d6..cdb63ef2 100644 --- a/test/Application.UnitTests/Mappings/MappingTests.cs +++ b/test/Application.UnitTests/Mappings/MappingTests.cs @@ -51,10 +51,12 @@ public void LocationDtoShouldMapCorrectlyToLocationTypeDto() } - private object GetInstanceOf(Type type) + private static object GetInstanceOf(Type type) { - if (type.GetConstructor(Type.EmptyTypes) != null) - return Activator.CreateInstance(type); + // Check for a parameterless constructor, including non-public ones + ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); + if (constructor != null) + return constructor.Invoke(null); // Type without parameterless constructor return FormatterServices.GetUninitializedObject(type);