Compare commits
2 Commits
v9.5.1
...
18c6f6f10e
| Author | SHA1 | Date | |
|---|---|---|---|
| 18c6f6f10e | |||
| 02c8e0ea3c |
@@ -12,6 +12,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPATapi.Client", "src\CPATa
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPATapi.Client.Tests", "test\CPATapi.Client.Tests\CPATapi.Client.Tests.csproj", "{17F37791-4F68-46D5-8CF5-5F1736F6776E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPATapi.Server.Tests", "test\CPATapi.Server.Tests\CPATapi.Server.Tests.csproj", "{72486DC9-2C7D-409B-9E14-6D90F67B92CC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -30,6 +32,10 @@ Global
|
||||
{17F37791-4F68-46D5-8CF5-5F1736F6776E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{17F37791-4F68-46D5-8CF5-5F1736F6776E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{17F37791-4F68-46D5-8CF5-5F1736F6776E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{72486DC9-2C7D-409B-9E14-6D90F67B92CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{72486DC9-2C7D-409B-9E14-6D90F67B92CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{72486DC9-2C7D-409B-9E14-6D90F67B92CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{72486DC9-2C7D-409B-9E14-6D90F67B92CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// <auto-generated/>
|
||||
#pragma warning disable CS0618
|
||||
using CPATapi.Client.Availability.Item;
|
||||
using CPATapi.Client.Availability.Users;
|
||||
using CPATapi.Client.Models;
|
||||
using Microsoft.Kiota.Abstractions.Extensions;
|
||||
using Microsoft.Kiota.Abstractions.Serialization;
|
||||
using Microsoft.Kiota.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace CPATapi.Client.Availability
|
||||
{
|
||||
@@ -16,11 +18,6 @@ namespace CPATapi.Client.Availability
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class AvailabilityRequestBuilder : BaseRequestBuilder
|
||||
{
|
||||
/// <summary>The users property</summary>
|
||||
public global::CPATapi.Client.Availability.Users.UsersRequestBuilder Users
|
||||
{
|
||||
get => new global::CPATapi.Client.Availability.Users.UsersRequestBuilder(PathParameters, RequestAdapter);
|
||||
}
|
||||
/// <summary>Gets an item from the CPATapi.Client.Availability.item collection</summary>
|
||||
/// <param name="position">Unique identifier of the item</param>
|
||||
/// <returns>A <see cref="global::CPATapi.Client.Availability.Item.WithUserItemRequestBuilder"/></returns>
|
||||
@@ -49,6 +46,55 @@ namespace CPATapi.Client.Availability
|
||||
public AvailabilityRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/Availability", rawUrl)
|
||||
{
|
||||
}
|
||||
/// <returns>A List<global::CPATapi.Client.Models.Availability></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<List<global::CPATapi.Client.Models.Availability>?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public async Task<List<global::CPATapi.Client.Models.Availability>> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
var collectionResult = await RequestAdapter.SendCollectionAsync<global::CPATapi.Client.Models.Availability>(requestInfo, global::CPATapi.Client.Models.Availability.CreateFromDiscriminatorValue, default, cancellationToken).ConfigureAwait(false);
|
||||
return collectionResult?.AsList();
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
|
||||
{
|
||||
#nullable restore
|
||||
#else
|
||||
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
|
||||
{
|
||||
#endif
|
||||
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
|
||||
requestInfo.Configure(requestConfiguration);
|
||||
requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
|
||||
return requestInfo;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="global::CPATapi.Client.Availability.AvailabilityRequestBuilder"/></returns>
|
||||
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
|
||||
public global::CPATapi.Client.Availability.AvailabilityRequestBuilder WithUrl(string rawUrl)
|
||||
{
|
||||
return new global::CPATapi.Client.Availability.AvailabilityRequestBuilder(rawUrl, RequestAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configuration for the request such as headers, query parameters, and middleware options.
|
||||
/// </summary>
|
||||
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
|
||||
public partial class AvailabilityRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace CPATapi.Client.Availability.Item
|
||||
/// <returns>A <see cref="global::CPATapi.Client.Models.Availability"/></returns>
|
||||
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
/// <exception cref="global::CPATapi.Client.Models.ProblemDetails">When receiving a 404 status code</exception>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public async Task<global::CPATapi.Client.Models.Availability?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
|
||||
@@ -46,7 +47,11 @@ namespace CPATapi.Client.Availability.Item
|
||||
{
|
||||
#endif
|
||||
var requestInfo = ToGetRequestInformation(requestConfiguration);
|
||||
return await RequestAdapter.SendAsync<global::CPATapi.Client.Models.Availability>(requestInfo, global::CPATapi.Client.Models.Availability.CreateFromDiscriminatorValue, default, cancellationToken).ConfigureAwait(false);
|
||||
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
|
||||
{
|
||||
{ "404", global::CPATapi.Client.Models.ProblemDetails.CreateFromDiscriminatorValue },
|
||||
};
|
||||
return await RequestAdapter.SendAsync<global::CPATapi.Client.Models.Availability>(requestInfo, global::CPATapi.Client.Models.Availability.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
/// <returns>A <see cref="RequestInformation"/></returns>
|
||||
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<PackageId>CPATapi.Client</PackageId>
|
||||
<Authors>Daniel Triendl</Authors>
|
||||
<Company>CP Solutions GmbH</Company>
|
||||
<Version>9.5.1</Version>
|
||||
<Version>9.6.0</Version>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -14,6 +14,14 @@ namespace CPATapi.Client.Models
|
||||
{
|
||||
/// <summary>Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.</summary>
|
||||
public IDictionary<string, object> AdditionalData { get; set; }
|
||||
/// <summary>The extension property</summary>
|
||||
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
|
||||
#nullable enable
|
||||
public string? Extension { get; set; }
|
||||
#nullable restore
|
||||
#else
|
||||
public string Extension { get; set; }
|
||||
#endif
|
||||
/// <summary>The loggedIn property</summary>
|
||||
public bool? LoggedIn { get; set; }
|
||||
/// <summary>The user property</summary>
|
||||
@@ -49,6 +57,7 @@ namespace CPATapi.Client.Models
|
||||
{
|
||||
return new Dictionary<string, Action<IParseNode>>
|
||||
{
|
||||
{ "extension", n => { Extension = n.GetStringValue(); } },
|
||||
{ "loggedIn", n => { LoggedIn = n.GetBoolValue(); } },
|
||||
{ "user", n => { User = n.GetStringValue(); } },
|
||||
};
|
||||
@@ -60,6 +69,7 @@ namespace CPATapi.Client.Models
|
||||
public virtual void Serialize(ISerializationWriter writer)
|
||||
{
|
||||
if(ReferenceEquals(writer, null)) throw new ArgumentNullException(nameof(writer));
|
||||
writer.WriteStringValue("extension", Extension);
|
||||
writer.WriteBoolValue("loggedIn", LoggedIn);
|
||||
writer.WriteStringValue("user", User);
|
||||
writer.WriteAdditionalData(AdditionalData);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"descriptionHash": "1B47F98D82C5E24FB3ABEDB3BF90615424A8F19620EA2621D23B7FC69F4F7BF27D512A11098EF4D8940C7D243DEEB59C0CA038264430AD9150B612F5046C8146",
|
||||
"descriptionHash": "3ADB4B190A2637B9EC01981B2508C539F2A582D95310D01FF97D2F2C068B9024CDC66F4D14F486265ED22314E9EEB2EA7CD3BF0F3D1ECC061BA7B9734B520A9D",
|
||||
"descriptionLocation": "../CPATapi.Server/CPATapi.Server.json",
|
||||
"lockFileVersion": "1.0.0",
|
||||
"kiotaVersion": "1.30.0",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<DockerfileContext>..\..</DockerfileContext>
|
||||
<OpenApiDocumentsDirectory>.</OpenApiDocumentsDirectory>
|
||||
<Version>9.5.1</Version>
|
||||
<Version>9.6.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -30,4 +30,8 @@
|
||||
<Folder Include="wwwroot\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="CPATapi.Server.Tests" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -11,19 +11,24 @@ namespace CPATapi.Server.Controllers;
|
||||
public class AvailabilityController(IZeitConsensRepository zeitConsens) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Route("users")]
|
||||
[ProducesResponseType<IEnumerable<string>>(StatusCodes.Status200OK)]
|
||||
[Route("")]
|
||||
[ProducesResponseType<IEnumerable<Availability>>(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetUsers()
|
||||
{
|
||||
return Ok(await zeitConsens.GetUsersAsync());
|
||||
return Ok(await zeitConsens.GetUsersAvailabilityAsync(DateTime.Now.Date, DateTime.Now.AddDays(1).Date));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{user}")]
|
||||
[ProducesResponseType<Availability>(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> GetAvailability(string user)
|
||||
{
|
||||
var stampCount = (await zeitConsens.GetStampsAsync(user, DateTime.Now.Date, DateTime.Now.AddDays(1).Date)).Count();
|
||||
return Ok(new Availability { User = user, LoggedIn = stampCount % 2 != 0 });
|
||||
var availability = await zeitConsens.GetUserAvailabilityAsync(user, DateTime.Now.Date, DateTime.Now.AddDays(1).Date);
|
||||
if (availability == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(availability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace CPATapi.Server.Interfaces;
|
||||
|
||||
public interface IZeitConsensRepository : IRepository
|
||||
{
|
||||
Task<IEnumerable<string>> GetUsersAsync();
|
||||
Task<IEnumerable<Stamp>> GetStampsAsync(string user, DateTime from, DateTime to);
|
||||
Task<IEnumerable<Availability>> GetUsersAvailabilityAsync(DateTime from, DateTime to);
|
||||
Task<Availability?> GetUserAvailabilityAsync(string user, DateTime from, DateTime to);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace CPATapi.Server.Models;
|
||||
@@ -5,7 +6,9 @@ namespace CPATapi.Server.Models;
|
||||
public class Availability
|
||||
{
|
||||
[JsonPropertyName("user")]
|
||||
public string User { get; set; }
|
||||
public required string MA_USER_NAME { get; set; }
|
||||
[JsonPropertyName("loggedIn")]
|
||||
public bool LoggedIn { get; set; }
|
||||
public bool LOGGED_IN { get; set; }
|
||||
[JsonPropertyName("extension")]
|
||||
public string? US_EXTENSION { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace CPATapi.Server.Models;
|
||||
|
||||
public class Stamp
|
||||
{
|
||||
public int MA_NR { get; set; }
|
||||
public DateTime BU_BU { get; set; }
|
||||
}
|
||||
@@ -6,29 +6,36 @@ namespace CPATapi.Server.Repository;
|
||||
|
||||
internal class ZeitConsensRepository(IConfiguration config) : Repository(config), IZeitConsensRepository
|
||||
{
|
||||
public async Task<IEnumerable<string>> GetUsersAsync()
|
||||
private const string SelectStampsQuery = """
|
||||
SELECT
|
||||
ma.MA_USER_NAME
|
||||
,bu.LOGGED_IN
|
||||
,us.US_EXTENSION
|
||||
FROM dbo.MA_DATEN ma
|
||||
INNER JOIN projectmanagement.dbo.CP_USER us on us.US_LOGINNAME = ma.MA_USER_NAME
|
||||
OUTER APPLY (
|
||||
SELECT count(*) % 2 AS LOGGED_IN
|
||||
FROM dbo.BU
|
||||
WHERE bu.BU_MA_NR = ma.MA_NR
|
||||
AND
|
||||
BU_BU >= @from AND BU_BU < @to
|
||||
) bu
|
||||
WHERE
|
||||
ma.MA_USER_AKTIV = 1
|
||||
""";
|
||||
|
||||
public async Task<IEnumerable<Availability>> GetUsersAvailabilityAsync(DateTime from, DateTime to)
|
||||
{
|
||||
await using var con = await OpenAsync("ZeitConsens");
|
||||
return await con.QueryAsync<string>("""
|
||||
SELECT DISTINCT MA_USER_NAME
|
||||
FROM dbo.MA_DATEN
|
||||
WHERE MA_USER_NAME IS NOT NULL AND MA_USER_AKTIV = 1
|
||||
ORDER BY MA_USER_NAME
|
||||
""");
|
||||
return await con.QueryAsync<Availability>(SelectStampsQuery, new { from, to });
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Stamp>> GetStampsAsync(string user, DateTime from, DateTime to)
|
||||
public async Task<Availability?> GetUserAvailabilityAsync(string user, DateTime from, DateTime to)
|
||||
{
|
||||
await using var con = await OpenAsync("ZeitConsens");
|
||||
return await con.QueryAsync<Stamp>("""
|
||||
SELECT
|
||||
MA_NR
|
||||
,BU_BU
|
||||
FROM dbo.BU
|
||||
INNER JOIN dbo.MA_DATEN on MA_NR = BU_MA_NR
|
||||
WHERE
|
||||
MA_USER_NAME = @user AND
|
||||
BU_BU >= @from AND BU_BU < @to
|
||||
return await con.QueryFirstOrDefaultAsync<Availability>($"""
|
||||
{SelectStampsQuery}
|
||||
AND ma.MA_USER_NAME = @user
|
||||
""", new { user, from, to });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using CPATapi.Client.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace CPATapi.Client.Tests;
|
||||
@@ -39,7 +40,17 @@ public class CPATapiClientTests
|
||||
{
|
||||
using var scope = CreateServices();
|
||||
var client = scope.ServiceProvider.GetRequiredService<CPATapiClient>();
|
||||
var availability = await client.Availability["Unknown"].GetAsync();
|
||||
Assert.ThrowsAsync<ProblemDetails>(async () => await client.Availability["Unknown"].GetAsync());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestAvailabilityGetAll()
|
||||
{
|
||||
using var scope = CreateServices();
|
||||
var client = scope.ServiceProvider.GetRequiredService<CPATapiClient>();
|
||||
var availability = await client.Availability.GetAsync();
|
||||
Assert.That(availability, Is.Not.Null);
|
||||
Assert.That(availability, Is.Not.Empty);
|
||||
Assert.That(availability, Has.Count.GreaterThan(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<UserSecretsId>a7b40068-a2f6-4c63-bbd9-0fd346908fb0</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.7.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\CPATapi.Server\CPATapi.Server.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="NUnit.Framework" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,38 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using CPATapi.Server.Repository;
|
||||
|
||||
namespace CPATapi.Server.Tests;
|
||||
|
||||
public class ZeitConsensRepositoryTest
|
||||
{
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
// the type specified here is just so the secrets library can
|
||||
// find the UserSecretId we added in the csproj file
|
||||
var builder = new ConfigurationBuilder().AddUserSecrets<ZeitConsensRepositoryTest>();
|
||||
|
||||
_configuration = builder.Build();
|
||||
}
|
||||
|
||||
private IConfigurationRoot _configuration { get; set; }
|
||||
|
||||
[Test]
|
||||
public async Task TestGetUsersAvailabilityAsync()
|
||||
{
|
||||
var zcRepo = new ZeitConsensRepository(_configuration);
|
||||
var availability= (await zcRepo.GetUsersAvailabilityAsync(DateTime.Now.Date, DateTime.Now.AddDays(1).Date)).ToList();
|
||||
Assert.That(availability, Is.Not.Empty);
|
||||
Assert.That(availability, Has.Count.GreaterThan(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetUserAvailabilityAsync()
|
||||
{
|
||||
var zcRepo = new ZeitConsensRepository(_configuration);
|
||||
var availability = await zcRepo.GetUserAvailabilityAsync("CPATRD", DateTime.Now.Date, DateTime.Now.AddDays(1).Date);
|
||||
Assert.That(availability, Is.Not.Null);
|
||||
Assert.That(availability.MA_USER_NAME, Is.EqualTo("CPATRD"));
|
||||
Assert.That(availability.US_EXTENSION, Is.EqualTo("203"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user