Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mark operations #81

Merged
merged 5 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Net;
using System.Net.Http.Json;
using Altinn.Correspondece.Tests.Factories;
using Altinn.Correspondence.Application.GetCorrespondencesResponse;
Expand Down Expand Up @@ -52,4 +53,46 @@ public async Task GetCorrespondenceDetails()
var getCorrespondenceOverviewResponse = await _client.GetAsync($"correspondence/api/v1/correspondence/{correspondenceId}/details");
Assert.True(getCorrespondenceOverviewResponse.IsSuccessStatusCode, await getCorrespondenceOverviewResponse.Content.ReadAsStringAsync());
}

[Fact]
public async Task MarkActions_CorrespondenceNotExists_ReturnNotFound()
{
var readResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/00000000-0100-0000-0000-000000000000/markasread", null);
Assert.Equal(HttpStatusCode.NotFound, readResponse.StatusCode);

var confirmResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/00000000-0100-0000-0000-000000000000/confirm", null);
Assert.Equal(HttpStatusCode.NotFound, confirmResponse.StatusCode);

var archiveResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/00000000-0100-0000-0000-000000000000/archive", null);
Assert.Equal(HttpStatusCode.NotFound, archiveResponse.StatusCode);
}

[Fact]
public async Task ReceiverMarkActions_CorrespondenceNotPublished_ReturnBadRequest()
{
var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", InitializeCorrespondenceFactory.BasicCorrespondence());
var correspondenceId = Guid.Parse(await initializeCorrespondenceResponse.Content.ReadAsStringAsync());

Console.WriteLine(correspondenceId);
var readResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/{correspondenceId}/markasread", null);
Assert.Equal(HttpStatusCode.BadRequest, readResponse.StatusCode);

var confirmResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/{correspondenceId}/confirm", null);
Assert.Equal(HttpStatusCode.BadRequest, confirmResponse.StatusCode);
}

/* [Fact]
public async Task ReceiverMarkActions_CorrespondencePublished_ReturnOk()
{
var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", InitializeCorrespondenceFactory.BasicCorrespondence());
var correspondenceId = Guid.Parse(await initializeCorrespondenceResponse.Content.ReadAsStringAsync());

//TODO: Add logic to publish correspondence
Ceredron marked this conversation as resolved.
Show resolved Hide resolved

var readResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/{correspondenceId}/markasread", null);
Assert.True(readResponse.IsSuccessStatusCode, await readResponse.Content.ReadAsStringAsync());

var confirmResponse = await _client.PostAsync($"correspondence/api/v1/correspondence/{correspondenceId}/confirm", null);
Assert.True(confirmResponse.IsSuccessStatusCode, await confirmResponse.Content.ReadAsStringAsync());
} */
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Altinn.Correspondence.Application.GetCorrespondenceOverviewCommand;
using Altinn.Correspondence.Application.GetCorrespondencesCommand;
using Altinn.Correspondence.Application.InitializeCorrespondenceCommand;
using Altinn.Correspondence.Application.UpdateCorrespondenceStatusCommand;
using Altinn.Correspondence.Core.Models.Enums;
using Altinn.Correspondence.Helpers;
using Altinn.Correspondence.Mappers;
Expand Down Expand Up @@ -169,15 +170,26 @@ public async Task<ActionResult<CorrespondencesExt>> GetCorrespondences(
/// <remarks>
/// Meant for Receivers
/// </remarks>
/// <returns>Ok</returns>
/// <returns>StatusId</returns>
[HttpPost]
[Route("{correspondenceId}/markasread")]
public async Task<ActionResult> MarkAsRead(
Guid correspondenceId)
Guid correspondenceId,
[FromServices] UpdateCorrespondenceStatusCommandHandler handler,
CancellationToken cancellationToken)
{
_logger.LogInformation("Marking Correspondence as read for {correspondenceId}", correspondenceId.ToString());

return Ok();
var commandResult = await handler.Process(new UpdateCorrespondenceStatusCommandRequest
{
CorrespondenceId = correspondenceId,
Status = CorrespondenceStatus.Read
}, cancellationToken);

return commandResult.Match(
data => Ok(data),
Problem
);
}

/// <summary>
Expand All @@ -186,15 +198,26 @@ public async Task<ActionResult> MarkAsRead(
/// <remarks>
/// Meant for Receivers
/// </remarks>
/// <returns>Ok</returns>
/// <returns>StatusId</returns>
[HttpPost]
[Route("{correspondenceId}/confirm")]
public async Task<ActionResult> Confirm(
Guid correspondenceId)
Guid correspondenceId,
[FromServices] UpdateCorrespondenceStatusCommandHandler handler,
CancellationToken cancellationToken)
{
_logger.LogInformation("Marking Correspondence as confirmed for {correspondenceId}", correspondenceId.ToString());

return Ok();
var commandResult = await handler.Process(new UpdateCorrespondenceStatusCommandRequest
{
CorrespondenceId = correspondenceId,
Status = CorrespondenceStatus.Confirmed
}, cancellationToken);

return commandResult.Match(
data => Ok(data),
Problem
);
}

/// <summary>
Expand All @@ -203,15 +226,26 @@ public async Task<ActionResult> Confirm(
/// <remarks>
/// Meant for Receivers
/// </remarks>
/// <returns>Ok</returns>
/// <returns>StatusId</returns>
[HttpPost]
[Route("{correspondenceId}/archive")]
public async Task<ActionResult> Archive(
Guid correspondenceId)
Guid correspondenceId,
[FromServices] UpdateCorrespondenceStatusCommandHandler handler,
CancellationToken cancellationToken)
{
_logger.LogInformation("Archiving Correspondence with id: {correspondenceId}", correspondenceId.ToString());

return Ok();
var commandResult = await handler.Process(new UpdateCorrespondenceStatusCommandRequest
{
CorrespondenceId = correspondenceId,
Status = CorrespondenceStatus.Archived
}, cancellationToken);

return commandResult.Match(
data => Ok(data),
Problem
);
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Altinn.Correspondence.Application/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Altinn.Correspondence.Application.InitializeAttachmentCommand;
using Altinn.Correspondence.Application.InitializeCorrespondenceCommand;
using Altinn.Correspondence.Application.UploadAttachmentCommand;
using Altinn.Correspondence.Application.UpdateCorrespondenceStatusCommand;
using Microsoft.Extensions.DependencyInjection;

namespace Altinn.Correspondence.Application;
Expand All @@ -22,6 +23,7 @@ public static void AddApplicationHandlers(this IServiceCollection services)
services.AddScoped<GetCorrespondenceOverviewCommandHandler>();
services.AddScoped<GetAttachmentOverviewCommandHandler>();
services.AddScoped<GetAttachmentDetailsCommandHandler>();
services.AddScoped<UpdateCorrespondenceStatusCommandHandler>();
services.AddScoped<UploadAttachmentCommandHandler>();
services.AddScoped<DownloadAttachmentQueryHandler>();
}
Expand Down
1 change: 1 addition & 0 deletions src/Altinn.Correspondence.Application/Errors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public static class Errors
public static Error UploadFailed = new(4, "Error occurred during upload", HttpStatusCode.BadGateway);
public static Error InvalidFileSize = new(5, "File must have content and has a max file size of 2GB", HttpStatusCode.BadRequest);
public static Error InvalidAttachmentStatus = new(6, "File has already been or is being uploaded", HttpStatusCode.BadRequest);
public static Error CorrespondenceNotPublished = new Error(7, "A correspondence can only be confirmed or read when it is published. See correspondence status.", HttpStatusCode.BadRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Altinn.Correspondence.Core.Models;
using Altinn.Correspondence.Core.Models.Enums;
using Altinn.Correspondence.Core.Repositories;
using OneOf;

namespace Altinn.Correspondence.Application.UpdateCorrespondenceStatusCommand;

public class UpdateCorrespondenceStatusCommandHandler : IHandler<UpdateCorrespondenceStatusCommandRequest, Guid>
{
private readonly ICorrespondenceRepository _correspondenceRepository;
private readonly ICorrespondenceStatusRepository _correspondenceStatusRepository;
public UpdateCorrespondenceStatusCommandHandler(ICorrespondenceRepository correspondenceRepository, ICorrespondenceStatusRepository correspondenceStatusRepository)
{
_correspondenceRepository = correspondenceRepository;
_correspondenceStatusRepository = correspondenceStatusRepository;
}

public async Task<OneOf<Guid, Error>> Process(UpdateCorrespondenceStatusCommandRequest request, CancellationToken cancellationToken)
{
var correspondence = await _correspondenceRepository.GetCorrespondenceById(request.CorrespondenceId, false, cancellationToken);
if (correspondence == null)
{
return Errors.CorrespondenceNotFound;
}

var currentStatus = await _correspondenceStatusRepository.GetLatestStatusByCorrespondenceId(request.CorrespondenceId, cancellationToken);
if ((request.Status == CorrespondenceStatus.Confirmed || request.Status == CorrespondenceStatus.Read) && currentStatus?.Status != CorrespondenceStatus.Published)
{
return Errors.CorrespondenceNotPublished;
}
if (currentStatus?.Status == request.Status)
{
return request.CorrespondenceId;
}

await _correspondenceStatusRepository.AddCorrespondenceStatus(new CorrespondenceStatusEntity
{
CorrespondenceId = request.CorrespondenceId,
Status = request.Status,
StatusChanged = DateTime.UtcNow,
StatusText = request.Status.ToString(),
}, cancellationToken);
return request.CorrespondenceId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Altinn.Correspondence.Core.Models.Enums;

namespace Altinn.Correspondence.Application.UpdateCorrespondenceStatusCommand;

public class UpdateCorrespondenceStatusCommandRequest
{
public Guid CorrespondenceId { get; set; }
public CorrespondenceStatus Status { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Altinn.Correspondence.Core.Models;

namespace Altinn.Correspondence.Core.Repositories
{
public interface ICorrespondenceStatusRepository
{
Task<Guid> AddCorrespondenceStatus(CorrespondenceStatusEntity Correspondence, CancellationToken cancellationToken);
Task<CorrespondenceStatusEntity?> GetLatestStatusByCorrespondenceId(Guid CorrespondenceId, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public static void AddPersistence(this IServiceCollection services)
services.AddScoped<IAttachmentRepository, AttachmentRepository>();
services.AddScoped<IAttachmentStatusRepository, AttachmentStatusRepository>();
services.AddScoped<ICorrespondenceRepository, CorrespondenceRepository>();
services.AddScoped<ICorrespondenceStatusRepository, CorrespondenceStatusRepository>();
services.AddScoped<IStorageRepository, StorageRepository>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Altinn.Correspondence.Core.Models;
using Altinn.Correspondence.Core.Repositories;
using Microsoft.EntityFrameworkCore;

namespace Altinn.Correspondence.Persistence.Repositories
{
public class CorrespondenceStatusRepository(ApplicationDbContext context) : ICorrespondenceStatusRepository
{
private readonly ApplicationDbContext _context = context;

public async Task<Guid> AddCorrespondenceStatus(CorrespondenceStatusEntity status, CancellationToken cancellationToken)
{
await _context.CorrespondenceStatuses.AddAsync(status, cancellationToken);
await _context.SaveChangesAsync();
return status.Id;
}

public async Task<CorrespondenceStatusEntity?> GetLatestStatusByCorrespondenceId(Guid CorrespondenceId, CancellationToken cancellationToken)
{
var status = await _context.CorrespondenceStatuses
.Where(s => s.CorrespondenceId == CorrespondenceId)
.OrderByDescending(s => s.StatusChanged)
.FirstOrDefaultAsync(cancellationToken);

return status;
}
}
}
Loading