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

chore: Summary cleaup #689

Merged
merged 4 commits into from
Sep 5, 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
8 changes: 5 additions & 3 deletions src/Fusion.Summary.Api/BaseController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ namespace Fusion.Summary.Api;

public class BaseController : ControllerBase
{
// TODO: Transition to ProblemDetails
protected NotFoundObjectResult DepartmentNotFound(string sapDepartmentId) =>
NotFound(new { message = $"Department with id '{sapDepartmentId}' was not found" });
protected ActionResult DepartmentNotFound(string sapDepartmentId) =>
FusionApiError.NotFound(sapDepartmentId, $"Department with sap id '{sapDepartmentId}' was not found");

protected ActionResult SapDepartmentIdRequired() =>
FusionApiError.InvalidOperation("SapDepartmentIdRequired", "SapDepartmentId route parameter is required");


protected Task DispatchAsync(IRequest command)
Expand Down
60 changes: 19 additions & 41 deletions src/Fusion.Summary.Api/Controllers/DepartmentsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,22 @@
using Fusion.Summary.Api.Controllers.Requests;
using Fusion.Summary.Api.Domain.Commands;
using Fusion.Summary.Api.Domain.Queries;
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using HttpRequestExtensions = Microsoft.ApplicationInsights.AspNetCore.Extensions.HttpRequestExtensions;

namespace Fusion.Summary.Api.Controllers;

/// <summary>
/// TODO: Add summary
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[ApiController]
public class DepartmentsController : BaseController
{
/// <summary />
/// TODO: Add summary
/// <returns></returns>
[HttpGet("departments")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(ApiDepartment[]), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetDepartmentsV1()
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<ApiDepartment[]>> GetDepartmentsV1()
{
#region Authorization

Expand All @@ -43,31 +36,19 @@ public async Task<IActionResult> GetDepartmentsV1()

#endregion Authorization

var ret = new List<ApiDepartment>();
var departments = await DispatchAsync(new GetAllDepartments());
larfeq marked this conversation as resolved.
Show resolved Hide resolved

// Query
var departments = (await DispatchAsync(new GetAllDepartments())).ToArray();

if (departments.Length == 0)
return NotFound();
else
{
foreach (var d in departments) ret.Add(ApiDepartment.FromQueryDepartment(d));
}
var apiDepartments = departments.Select(ApiDepartment.FromQueryDepartment);

return Ok(ret);
return Ok(apiDepartments);
larfeq marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary />
/// TODO: Add summary
/// <returns></returns>
[HttpGet("departments/{sapDepartmentId}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(ApiDepartment), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetDepartmentV1(string sapDepartmentId)
public async Task<ActionResult<ApiDepartment>> GetDepartmentV1(string sapDepartmentId)
{
#region Authorization

Expand All @@ -83,7 +64,7 @@ public async Task<IActionResult> GetDepartmentV1(string sapDepartmentId)
#endregion Authorization

if (string.IsNullOrWhiteSpace(sapDepartmentId))
return BadRequest("SapDepartmentId route parameter is required");
return SapDepartmentIdRequired();

var department = await DispatchAsync(new GetDepartment(sapDepartmentId));

Expand All @@ -94,15 +75,12 @@ public async Task<IActionResult> GetDepartmentV1(string sapDepartmentId)
return Ok(ApiDepartment.FromQueryDepartment(department));
}

/// <summary />
/// TODO: Add summary
/// <returns></returns>

[HttpPut("departments/{sapDepartmentId}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> PutV1(string sapDepartmentId, [FromBody] PutDepartmentRequest request)
{
Expand All @@ -120,7 +98,7 @@ public async Task<IActionResult> PutV1(string sapDepartmentId, [FromBody] PutDep
#endregion Authorization

if (string.IsNullOrWhiteSpace(sapDepartmentId))
return BadRequest("SapDepartmentId route parameter is required");
return SapDepartmentIdRequired();

var personIdentifiers = request.ResourceOwnersAzureUniqueId
.Concat(request.DelegateResourceOwnersAzureUniqueId)
Expand All @@ -131,7 +109,7 @@ public async Task<IActionResult> PutV1(string sapDepartmentId, [FromBody] PutDep
.ToList();

if (unresolvedProfiles.Count != 0)
return BadRequest($"Profiles: {string.Join(',', unresolvedProfiles)} could not be resolved");
return FusionApiError.NotFound(string.Join(',', unresolvedProfiles), "Profiles could not be resolved");


var department = await DispatchAsync(new GetDepartment(sapDepartmentId));
Expand All @@ -146,7 +124,7 @@ await DispatchAsync(
request.ResourceOwnersAzureUniqueId,
request.DelegateResourceOwnersAzureUniqueId));

return Created();
return Created(Request.GetUri(), null);
}

// Check if department owners has changed
Expand All @@ -160,10 +138,10 @@ await DispatchAsync(
request.ResourceOwnersAzureUniqueId,
request.DelegateResourceOwnersAzureUniqueId));

return Ok();
return NoContent();
}

// No change
return Ok();
return NoContent();
}
}
31 changes: 18 additions & 13 deletions src/Fusion.Summary.Api/Controllers/SummaryReportsController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net.Mime;
using Fusion.AspNetCore.Api;
using Fusion.AspNetCore.FluentAuthorization;
using Fusion.AspNetCore.OData;
using Fusion.Authorization;
Expand All @@ -7,6 +8,7 @@
using Fusion.Summary.Api.Controllers.Requests;
using Fusion.Summary.Api.Domain.Commands;
using Fusion.Summary.Api.Domain.Queries;
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

Expand All @@ -18,14 +20,13 @@ namespace Fusion.Summary.Api.Controllers;
public class SummaryReportsController : BaseController
{
[HttpGet("resource-owners-summary-reports/{sapDepartmentId}/weekly")]
[Produces(MediaTypeNames.Application.Json)]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ODataFilter(nameof(ApiWeeklySummaryReport.Period))]
[ODataOrderBy(nameof(ApiWeeklySummaryReport.Period), nameof(ApiWeeklySummaryReport.Id))]
[ODataTop(100), ODataSkip]
[ApiVersion("1.0")]
public async Task<ActionResult<ApiCollection<ApiWeeklySummaryReport>>> GetWeeklySummaryReportsV1(
[FromRoute] string sapDepartmentId, ODataQueryParams query)
{
Expand All @@ -44,7 +45,7 @@ await Request.RequireAuthorizationAsync(r =>
#endregion

if (string.IsNullOrWhiteSpace(sapDepartmentId))
return BadRequest("SapDepartmentId route parameter is required");
return SapDepartmentIdRequired();

if (await DispatchAsync(new GetDepartment(sapDepartmentId)) is null)
return DepartmentNotFound(sapDepartmentId);
Expand All @@ -55,12 +56,16 @@ await Request.RequireAuthorizationAsync(r =>
.FromQueryCollection(queryReports, ApiWeeklySummaryReport.FromQuerySummaryReport));
}

/// <summary>
/// Summary report key is composed of the department sap id and the period date.
/// If a report already exists for the given period, it will be replaced.
/// </summary>
[HttpPut("resource-owners-summary-reports/{sapDepartmentId}/weekly")]
[Produces(MediaTypeNames.Application.Json)]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> PutWeeklySummaryReportV1([FromRoute] string sapDepartmentId,
[FromBody] PutWeeklySummaryReportRequest request)
{
Expand All @@ -79,18 +84,18 @@ await Request.RequireAuthorizationAsync(r =>
#endregion

if (string.IsNullOrWhiteSpace(sapDepartmentId))
return BadRequest("SapDepartmentId route parameter is required");
return SapDepartmentIdRequired();

if (await DispatchAsync(new GetDepartment(sapDepartmentId)) is null)
return DepartmentNotFound(sapDepartmentId);

if (request.Period.DayOfWeek != DayOfWeek.Monday)
return BadRequest("Period date must be the first day of the week");
return FusionApiError.InvalidOperation("InvalidPeriod", "Weekly summary report period date must be a monday");

var command = new PutWeeklySummaryReport(sapDepartmentId, request);

await DispatchAsync(command);
var newReportCreated = await DispatchAsync(command);

return NoContent();
return newReportCreated ? Created(Request.GetUri(), null) : NoContent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Fusion.Summary.Api.Domain.Commands;

public class PutWeeklySummaryReport : IRequest
public class PutWeeklySummaryReport : IRequest<bool>
{
public string SapDepartmentId { get; private set; }

Expand All @@ -20,7 +20,7 @@ public PutWeeklySummaryReport(string sapDepartmentId, PutWeeklySummaryReportRequ
}


public class Handler : IRequestHandler<PutWeeklySummaryReport>
public class Handler : IRequestHandler<PutWeeklySummaryReport, bool>
{
private readonly SummaryDbContext _dbContext;

Expand All @@ -29,7 +29,7 @@ public Handler(SummaryDbContext dbContext)
_dbContext = dbContext;
}

public async Task Handle(PutWeeklySummaryReport request, CancellationToken cancellationToken)
public async Task<bool> Handle(PutWeeklySummaryReport request, CancellationToken cancellationToken)
{
if (!await _dbContext.Departments.AnyAsync(d => d.DepartmentSapId == request.SapDepartmentId,
cancellationToken: cancellationToken))
Expand Down Expand Up @@ -83,6 +83,9 @@ public async Task Handle(PutWeeklySummaryReport request, CancellationToken cance
_dbContext.WeeklySummaryReports.Add(dbSummaryReport);

await _dbContext.SaveChangesAsync(cancellationToken);

// return true if a new report was created
return existingReport is null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
[
{
"environment": "pr",
"disabledFunctions": [
"weekly-department-recipients-sync",
"weekly-department-summary-sender",
"weekly-department-summary-worker"
]
"disabledFunctions": []
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public DepartmentResourceOwnerSync(
/// <exception cref="Exception"></exception>
[FunctionName("weekly-department-recipients-sync")]
public async Task RunAsync(
[TimerTrigger("0 05 00 * * *", RunOnStartup = false)]
[TimerTrigger("0 05 00 * * MON", RunOnStartup = false)]
TimerInfo timerInfo, CancellationToken cancellationToken
)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public WeeklyDepartmentSummarySender(ISummaryApiClient summaryApiClient, INotifi
}

[FunctionName("weekly-department-summary-sender")]
public async Task RunAsync([TimerTrigger("0 0 8 * * 1", RunOnStartup = false)] TimerInfo timerInfo)
public async Task RunAsync([TimerTrigger("0 0 8 * * MON", RunOnStartup = false)] TimerInfo timerInfo)
{
var departments = await summaryApiClient.GetDepartmentsAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,44 @@ public async Task PutAndGetWeeklySummaryReport_ShouldReturnReport()


var response = await _client.PutWeeklySummaryReportAsync(department.DepartmentSapId);
response.Should().BeNoContent();
response.Should().BeCreated();

var getResponse = await _client.GetWeeklySummaryReportsAsync(department.DepartmentSapId);
getResponse.Should().BeSuccessfull();
getResponse.Value!.Items.Should().HaveCount(1);
}

[Fact]
public async Task PutAndUpdateWeeklySummaryReport_ShouldReturnNoContent()
{
using var adminScope = _fixture.AdminScope();
var testUser = _fixture.Fusion.CreateUser().AsEmployee().AzureUniqueId!.Value;

var department = await _client.PutDepartmentAsync(testUser);

var response = await _client.PutWeeklySummaryReportAsync(department.DepartmentSapId);
response.Should().BeCreated();

response = await _client.PutWeeklySummaryReportAsync(department.DepartmentSapId);
response.Should().BeNoContent();
}

[Fact]
public async Task PutWeeklySummaryReport_WithInvalidPeriodDate_ShouldReturnBadRequest()
{
using var adminScope = _fixture.AdminScope();
var testUser = _fixture.Fusion.CreateUser().AsEmployee().AzureUniqueId!.Value;

var department = await _client.PutDepartmentAsync(testUser);

var response = await _client.PutWeeklySummaryReportAsync(department.DepartmentSapId, (report) =>
{
var nowDate = DateTime.UtcNow;
if (nowDate.DayOfWeek == DayOfWeek.Monday)
report.Period = nowDate.AddDays(1);
report.Period = nowDate;
});

response.Should().BeBadRequest();
}
}
Loading