Skip to content

Commit

Permalink
feat(certificate): get company certificates by filter and sorting (#515)
Browse files Browse the repository at this point in the history
Refs: #470
Co-authored-by: Phil Schneider <[email protected]>
Reviewed-by: Phil Schneider <[email protected]>
  • Loading branch information
AnuragNagpure and Phil91 authored Feb 17, 2024
1 parent 3ab02b1 commit 90acec2
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -577,4 +577,11 @@ await _mailingService.SendMails(requesterEmail, mailParameters, Enumerable.Repea
/// <inheritdoc />
public IAsyncEnumerable<VerifiedCredentialTypeId> GetCertificateTypes() =>
_portalRepositories.GetInstance<ICompanySsiDetailsRepository>().GetCertificateTypes(_identityData.CompanyId);

public Task<Pagination.Response<CompanyCertificateData>> GetAllCompanyCertificatesAsync(int page, int size, CertificateSorting? sorting, CompanyCertificateStatusId? certificateStatus, CompanyCertificateTypeId? certificateType) =>
Pagination.CreateResponseAsync(
page,
size,
_settings.MaxPageSize,
_portalRepositories.GetInstance<ICompanyCertificateRepository>().GetActiveCompanyCertificatePaginationSource(sorting, certificateStatus, certificateType, _identityData.CompanyId));
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,6 @@ public interface ICompanyDataBusinessLogic
IAsyncEnumerable<VerifiedCredentialTypeId> GetCertificateTypes();

Task CreateCompanyCertificate(CompanyCertificateCreationData data, CancellationToken cancellationToken);

Task<Pagination.Response<CompanyCertificateData>> GetAllCompanyCertificatesAsync(int page, int size, CertificateSorting? sorting, CompanyCertificateStatusId? certificateStatus, CompanyCertificateTypeId? certificateType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,27 @@ public async Task<NoContentResult> CreateCompanyCertificate([FromForm] CompanyCe
return NoContent();
}

/// <summary>
/// Retrieves all company certificates with respect userId.
/// </summary>
/// <param name="page" example="0">Optional the page of company certificate.</param>
/// <param name="size" example="15">Amount of company certificate, default is 15.</param>
/// <param name="sorting" example="CertificateTypeAsc">Optional Sorting of the pagination</param>
/// <param name="certificateStatus" example="">Optional filter for company certificate status</param>
/// <param name="certificateType" example="">Optional filter for company certificate type</param>
/// <returns>Collection of all active company certificates.</returns>
/// <remarks>Example: GET /api/administration/companydata/companyCertificates</remarks>
/// <response code="200">Returns the list of all active company certificates.</response>
[HttpGet]
[Route("companyCertificates")]
[Authorize(Roles = "view_certificates")]
[Authorize(Policy = PolicyTypes.ValidIdentity)]
[Authorize(Policy = PolicyTypes.ValidCompany)]
[ProducesResponseType(typeof(Pagination.Response<ServiceOverviewData>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public Task<Pagination.Response<CompanyCertificateData>> GetAllCompanyCertificatesAsync([FromQuery] int page = 0, [FromQuery] int size = 15, [FromQuery] CertificateSorting? sorting = null, [FromQuery] CompanyCertificateStatusId? certificateStatus = null, [FromQuery] CompanyCertificateTypeId? certificateType = null) =>
_logic.GetAllCompanyCertificatesAsync(page, size, sorting, certificateStatus, certificateType);

/// <summary>
/// Gets all outstanding, existing and inactive credentials
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/********************************************************************************
* Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;

public enum CertificateSorting
{
/// <summary>
/// Ascending by certificateType
/// </summary>
CertificateTypeAsc = 1,

/// <summary>
/// Descending by certificateType
/// </summary>
CertificateTypeDesc = 2,

/// <summary>
/// Ascending by expiryDate
/// </summary>
ExpiryDateAsc = 3,

/// <summary>
/// Descending by expiryDate
/// </summary>
ExpiryDateDesc = 4,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/********************************************************************************
* Copyright (c) 2021, 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;

namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;

public record CompanyCertificateData(
CompanyCertificateTypeId companyCertificateType,
CompanyCertificateStatusId companyCertificateStatus,
Guid documentId,
DateTimeOffset validFrom,
DateTimeOffset? validTill
);
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
********************************************************************************/

using Microsoft.EntityFrameworkCore;
using Org.Eclipse.TractusX.Portal.Backend.Framework.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;

namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
Expand Down Expand Up @@ -52,4 +51,33 @@ public CompanyCertificate CreateCompanyCertificate(Guid companyId, CompanyCertif
setOptionalFields?.Invoke(companyCertificate);
return _context.CompanyCertificates.Add(companyCertificate).Entity;
}

public Func<int, int, Task<Pagination.Source<CompanyCertificateData>?>> GetActiveCompanyCertificatePaginationSource(CertificateSorting? sorting, CompanyCertificateStatusId? certificateStatus, CompanyCertificateTypeId? certificateType, Guid companyId) =>
(skip, take) => Pagination.CreateSourceQueryAsync(
skip,
take,
_context.CompanyCertificates
.AsNoTracking()
.Where(x =>
x.CompanyId == companyId &&
x.CompanyCertificateStatusId == CompanyCertificateStatusId.ACTIVE &&
(certificateStatus == null || x.CompanyCertificateStatusId == certificateStatus) &&
(certificateType == null || x.CompanyCertificateTypeId == certificateType))
.GroupBy(x => x.CompanyId),
sorting switch
{
CertificateSorting.CertificateTypeAsc => (IEnumerable<CompanyCertificate> cc) => cc.OrderBy(x => x.CompanyCertificateTypeId),
CertificateSorting.CertificateTypeDesc => (IEnumerable<CompanyCertificate> cc) => cc.OrderByDescending(x => x.CompanyCertificateTypeId),
CertificateSorting.ExpiryDateAsc => (IEnumerable<CompanyCertificate> cc) => cc.OrderBy(x => x.ValidTill),
CertificateSorting.ExpiryDateDesc => (IEnumerable<CompanyCertificate> cc) => cc.OrderByDescending(x => x.ValidTill),
_ => null
},
companyCertificate => new CompanyCertificateData(
companyCertificate.CompanyCertificateTypeId,
companyCertificate.CompanyCertificateStatusId,
companyCertificate.DocumentId,
companyCertificate.ValidFrom,
companyCertificate.ValidTill
))
.SingleOrDefaultAsync();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;

Expand All @@ -40,4 +42,10 @@ public interface ICompanyCertificateRepository
/// <param name="setOptionalFields">Action to set optional fields</param>
/// <returns>The created entity</returns>
CompanyCertificate CreateCompanyCertificate(Guid companyId, CompanyCertificateTypeId companyCertificateTypeId, Guid docId, Action<CompanyCertificate>? setOptionalFields = null);

/// <summary>
/// Gets all company certificate data from the persistence storage as pagination
/// </summary>
/// <returns>Returns an Pagination</returns>
Func<int, int, Task<Pagination.Source<CompanyCertificateData>?>> GetActiveCompanyCertificatePaginationSource(CertificateSorting? sorting, CompanyCertificateStatusId? certificateStatus, CompanyCertificateTypeId? certificateType, Guid companyId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ private async Task SeedBaseEntity(CancellationToken cancellationToken)
await SeedTableForBaseEntity<TechnicalUserProfile>("technical_user_profiles", cancellationToken).ConfigureAwait(false);
await SeedTableForBaseEntity<CompanySsiDetail>("company_ssi_details", cancellationToken).ConfigureAwait(false);
await SeedTableForBaseEntity<VerifiedCredentialExternalTypeUseCaseDetailVersion>("verified_credential_external_type_use_case_detail_versions", cancellationToken).ConfigureAwait(false);
await SeedTableForBaseEntity<CompanyCertificate>("company_certificates", cancellationToken).ConfigureAwait(false);
}

private async Task SeedTableForBaseEntity<T>(string fileName, CancellationToken cancellationToken) where T : class, IBaseEntity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Base;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Document = Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities.Document;

namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities;

public class CompanyCertificate
public class CompanyCertificate : IBaseEntity
{
private CompanyCertificate() { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Custodian.Library;
using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Extensions;
Expand Down Expand Up @@ -1564,6 +1565,39 @@ public async Task GetCertificateTypes_WithFilter_ReturnsList()

#endregion

#region GetAllCompanyCertificates

[Fact]
public async Task GetAllCompanyCertificatesAsync_WithDefaultRequest_GetsExpectedEntries()
{
// Arrange
SetupPagination();
var sut = _fixture.Create<CompanyDataBusinessLogic>();

// Act
var result = await sut.GetAllCompanyCertificatesAsync(0, 5, null, null, null);

// Assert
result.Content.Should().HaveCount(3);
}

[Fact]
public async Task GetAllCompanyCertificatesAsync_WithSmallSize_GetsExpectedEntries()
{
// Arrange
const int expectedCount = 3;
SetupPagination(expectedCount);
var sut = _fixture.Create<CompanyDataBusinessLogic>();

// Act
var result = await sut.GetAllCompanyCertificatesAsync(0, expectedCount, null, null, null);

// Assert
result.Content.Should().HaveCount(expectedCount);
}

#endregion

#region Setup

private void SetupCreateUseCaseParticipation()
Expand All @@ -1590,5 +1624,16 @@ private void SetupCreateCompanyCertificate()
.Returns(false);
}

private void SetupPagination(int count = 5)
{
var companyCertificateDetailData = _fixture.CreateMany<CompanyCertificateData>(count);
var paginationResult = (int skip, int take) => Task.FromResult(new Pagination.Source<CompanyCertificateData>(companyCertificateDetailData.Count(), companyCertificateDetailData.Skip(skip).Take(take)));

A.CallTo(() => _companyCertificateRepository.GetActiveCompanyCertificatePaginationSource(A<CertificateSorting?>._, A<CompanyCertificateStatusId?>._, A<CompanyCertificateTypeId?>._, A<Guid>._))
.Returns(paginationResult);

A.CallTo(() => _portalRepositories.GetInstance<ICompanyCertificateRepository>()).Returns(_companyCertificateRepository);
}

#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Microsoft.EntityFrameworkCore;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Tests.Setup;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;

namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Tests;
Expand Down Expand Up @@ -83,6 +82,60 @@ public async Task CreateCompanyCertificateData_WithValidData_ReturnsExpected()
}
#endregion

#region GetAllCertificateData

[Theory]
[InlineData(CertificateSorting.CertificateTypeAsc)]
[InlineData(CertificateSorting.CertificateTypeDesc)]
public async Task GetAllCertificates_ReturnsExpectedResult(CertificateSorting sorting)
{
// Arrange
var sut = await CreateSut().ConfigureAwait(false);

// Act
var companyCertificateDetail = await sut.GetActiveCompanyCertificatePaginationSource(sorting, null, null, new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87"))(0, 15).ConfigureAwait(false);

// Assert
companyCertificateDetail.Should().NotBeNull();
companyCertificateDetail!.Count.Should().Be(6);
companyCertificateDetail.Data.Should().HaveCount(6);
if (sorting == CertificateSorting.CertificateTypeAsc)
{
companyCertificateDetail.Data.Select(data => data.companyCertificateType).Should().BeInAscendingOrder();
}
if (sorting == CertificateSorting.CertificateTypeDesc)
{
companyCertificateDetail.Data.Select(data => data.companyCertificateType).Should().BeInDescendingOrder();
}
}

[Theory]
[InlineData(CompanyCertificateStatusId.ACTIVE, CompanyCertificateTypeId.AEO_CTPAT_Security_Declaration, 0, 2, 1, 1)]
[InlineData(CompanyCertificateStatusId.ACTIVE, CompanyCertificateTypeId.ISO_9001, 0, 2, 1, 1)]
[InlineData(CompanyCertificateStatusId.INACTVIE, CompanyCertificateTypeId.IATF, 0, 2, 0, 0)]
public async Task GetAllCertificates_WithExistingCompanyCertificateAndCertificateType_ReturnsExpectedResult(CompanyCertificateStatusId companyCertificateStatusId, CompanyCertificateTypeId companyCertificateTypeId, int page, int size, int count, int numData)
{
// Arrange
var sut = await CreateSut().ConfigureAwait(false);

// Act
var companyCertificateDetail = await sut.GetActiveCompanyCertificatePaginationSource(null, companyCertificateStatusId, companyCertificateTypeId, new Guid("2dc4249f-b5ca-4d42-bef1-7a7a950a4f87"))(page, size).ConfigureAwait(false);

// Assert
if (count == 0)
{
companyCertificateDetail.Should().BeNull();
}
else
{
companyCertificateDetail.Should().NotBeNull();
companyCertificateDetail!.Count.Should().Be(count);
companyCertificateDetail.Data.Should().HaveCount(numData);
}
}

#endregion

#region Setup
private async Task<CompanyCertificateRepository> CreateSut()
{
Expand Down
Loading

0 comments on commit 90acec2

Please sign in to comment.