diff --git a/server/3cx_Tapi.sln b/server/3cx_Tapi.sln
index 6bd12f8..ea8368f 100644
--- a/server/3cx_Tapi.sln
+++ b/server/3cx_Tapi.sln
@@ -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
diff --git a/server/src/CPATapi.Server/CPATapi.Server.csproj b/server/src/CPATapi.Server/CPATapi.Server.csproj
index 008d76e..96ceb73 100644
--- a/server/src/CPATapi.Server/CPATapi.Server.csproj
+++ b/server/src/CPATapi.Server/CPATapi.Server.csproj
@@ -30,4 +30,8 @@
+
+
+
+
diff --git a/server/src/CPATapi.Server/Controllers/AvailabilityController.cs b/server/src/CPATapi.Server/Controllers/AvailabilityController.cs
index 0c9b2a9..df36957 100644
--- a/server/src/CPATapi.Server/Controllers/AvailabilityController.cs
+++ b/server/src/CPATapi.Server/Controllers/AvailabilityController.cs
@@ -11,19 +11,24 @@ namespace CPATapi.Server.Controllers;
public class AvailabilityController(IZeitConsensRepository zeitConsens) : ControllerBase
{
[HttpGet]
- [Route("users")]
- [ProducesResponseType>(StatusCodes.Status200OK)]
+ [Route("")]
+ [ProducesResponseType>(StatusCodes.Status200OK)]
public async Task GetUsers()
{
- return Ok(await zeitConsens.GetUsersAsync());
+ return Ok(await zeitConsens.GetUsersAvailabilityAsync(DateTime.Now.Date, DateTime.Now.AddDays(1).Date));
}
[HttpGet]
[Route("{user}")]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task 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);
}
}
diff --git a/server/src/CPATapi.Server/Interfaces/IZeitConsensRepository.cs b/server/src/CPATapi.Server/Interfaces/IZeitConsensRepository.cs
index 3a0024c..a7ae06b 100644
--- a/server/src/CPATapi.Server/Interfaces/IZeitConsensRepository.cs
+++ b/server/src/CPATapi.Server/Interfaces/IZeitConsensRepository.cs
@@ -4,6 +4,6 @@ namespace CPATapi.Server.Interfaces;
public interface IZeitConsensRepository : IRepository
{
- Task> GetUsersAsync();
- Task> GetStampsAsync(string user, DateTime from, DateTime to);
+ Task> GetUsersAvailabilityAsync(DateTime from, DateTime to);
+ Task GetUserAvailabilityAsync(string user, DateTime from, DateTime to);
}
diff --git a/server/src/CPATapi.Server/Models/Availability.cs b/server/src/CPATapi.Server/Models/Availability.cs
index 24d2e19..73e295c 100644
--- a/server/src/CPATapi.Server/Models/Availability.cs
+++ b/server/src/CPATapi.Server/Models/Availability.cs
@@ -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; }
}
diff --git a/server/src/CPATapi.Server/Models/Stamp.cs b/server/src/CPATapi.Server/Models/Stamp.cs
deleted file mode 100644
index 5ad9a15..0000000
--- a/server/src/CPATapi.Server/Models/Stamp.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace CPATapi.Server.Models;
-
-public class Stamp
-{
- public int MA_NR { get; set; }
- public DateTime BU_BU { get; set; }
-}
diff --git a/server/src/CPATapi.Server/Repository/ZeitConsensRepository.cs b/server/src/CPATapi.Server/Repository/ZeitConsensRepository.cs
index 28344a4..4772d1c 100644
--- a/server/src/CPATapi.Server/Repository/ZeitConsensRepository.cs
+++ b/server/src/CPATapi.Server/Repository/ZeitConsensRepository.cs
@@ -6,29 +6,36 @@ namespace CPATapi.Server.Repository;
internal class ZeitConsensRepository(IConfiguration config) : Repository(config), IZeitConsensRepository
{
- public async Task> 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> GetUsersAvailabilityAsync(DateTime from, DateTime to)
{
await using var con = await OpenAsync("ZeitConsens");
- return await con.QueryAsync("""
- 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(SelectStampsQuery, new { from, to });
}
- public async Task> GetStampsAsync(string user, DateTime from, DateTime to)
+ public async Task GetUserAvailabilityAsync(string user, DateTime from, DateTime to)
{
await using var con = await OpenAsync("ZeitConsens");
- return await con.QueryAsync("""
- 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($"""
+ {SelectStampsQuery}
+ AND ma.MA_USER_NAME = @user
""", new { user, from, to });
}
}
diff --git a/server/test/CPATapi.Server.Tests/CPATapi.Server.Tests.csproj b/server/test/CPATapi.Server.Tests/CPATapi.Server.Tests.csproj
new file mode 100644
index 0000000..7f3e199
--- /dev/null
+++ b/server/test/CPATapi.Server.Tests/CPATapi.Server.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net10.0
+ latest
+ enable
+ enable
+ false
+ a7b40068-a2f6-4c63-bbd9-0fd346908fb0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/test/CPATapi.Server.Tests/ZeitConsensRepositoryTests.cs b/server/test/CPATapi.Server.Tests/ZeitConsensRepositoryTests.cs
new file mode 100644
index 0000000..2bb80cc
--- /dev/null
+++ b/server/test/CPATapi.Server.Tests/ZeitConsensRepositoryTests.cs
@@ -0,0 +1,37 @@
+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();
+
+ _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);
+ }
+
+ [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"));
+ }
+}