fix: load ticket history through journal portal api

This commit is contained in:
Meik
2026-07-01 00:50:23 +02:00
parent 45b8e1d223
commit 258ca8a837
3 changed files with 123 additions and 22 deletions

View File

@@ -13,7 +13,7 @@
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<M42ExtensionId>6673a25d-33d6-4072-91d9-abed4be1a966</M42ExtensionId>
<M42AssemblyPattern>C4ITF4SD*.*</M42AssemblyPattern>
<M42PackageVersion>1.4.0.30</M42PackageVersion>
<M42PackageVersion>1.4.0.31</M42PackageVersion>
<M42BuildPackage>true</M42BuildPackage>
</PropertyGroup>

View File

@@ -1408,9 +1408,28 @@ namespace C4IT.F4SD
try
{
await Task.Delay(0);
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
var entries = LoadJournalEntries(activityEOID);
LogEntry($"{entries.Count} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
return CreateTicketJournalItems(activityEOID, entries);
}
catch (MissingMethodException E)
{
return F4SDM42WebApiController.CreateMissingMethodDiagnostics("GetJournalEntries helper", activityEOID, E);
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
internal static List<cTicketJournalItem> CreateTicketJournalItems(Guid activityEOID, IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo> entries)
{
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
for (int i = 0; i < entries.Count; i++)
{
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
@@ -1430,22 +1449,9 @@ namespace C4IT.F4SD
IsVisibleForUser = item.VisibleInPortal
});
}
return journalEntries;
}
catch (MissingMethodException E)
{
return F4SDM42WebApiController.CreateMissingMethodDiagnostics("GetJournalEntries helper", activityEOID, E);
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
private static IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo> LoadJournalEntries(Guid activityEOID)
{

View File

@@ -45,6 +45,10 @@ namespace C4IT.F4SD
private readonly F4SDHelperService _f4stHelperService;
private const string TeamsNotificationServiceTypeName = "Matrix42.Contracts.Platform.MsTeams.ITeamsNotificationService";
private const string StorageServiceTypeName = "Matrix42.StorageService.Contracts.IStorageService";
private const int JournalStart = 0;
private const int JournalCount = 50;
private const int JournalTimeOffset = 120;
private const string JournalObjectLinkTemplate = "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>";
public string BaseUrl => Request?.RequestUri == null ? string.Empty : $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}";
public string EndpointBaseUrl => $"{BaseUrl}/m42Services/api/c4itf4sdwebapi";
@@ -304,6 +308,13 @@ namespace C4IT.F4SD
{
try
{
var journalPortalEntries = await TryGetJournalPortalEntries(objectId);
if (journalPortalEntries != null)
{
LogEntry($"{journalPortalEntries.Count} Journal entries loaded from Matrix42 JournalPortalController for ObjectID={objectId}", LogLevels.Debug);
return F4SDHelperService.CreateTicketJournalItems(objectId, journalPortalEntries);
}
return await _f4stHelperService.GetJournalEntries(objectId);
}
catch (MissingMethodException ex)
@@ -312,6 +323,90 @@ namespace C4IT.F4SD
}
}
private async Task<IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo>> TryGetJournalPortalEntries(Guid objectId)
{
if (Request?.RequestUri == null)
return null;
foreach (var requestUri in BuildJournalPortalUris(objectId))
{
try
{
using (var handler = new HttpClientHandler { UseDefaultCredentials = true, AutomaticDecompression = DecompressionMethods.All })
using (var client = new HttpClient(handler))
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
client.Timeout = TimeSpan.FromSeconds(15);
CopyIncomingHeaders(request);
using (var response = await client.SendAsync(request))
{
var responseText = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
LogEntry($"Matrix42 JournalPortalController returned {(int)response.StatusCode} {response.ReasonPhrase} for {requestUri}. {responseText}", LogLevels.Warning);
continue;
}
var entries = DeserializeJournalPortalEntries(responseText);
if (entries != null)
return entries;
LogEntry($"Matrix42 JournalPortalController response could not be deserialized for {requestUri}. {responseText}", LogLevels.Warning);
}
}
}
catch (Exception ex)
{
LogEntry($"Matrix42 JournalPortalController request failed for {requestUri}. {ex.GetType().FullName}: {ex.Message}", LogLevels.Warning);
}
}
return null;
}
private IEnumerable<Uri> BuildJournalPortalUris(Guid objectId)
{
var query = $"objectId={Uri.EscapeDataString(objectId.ToString())}&start={JournalStart}&count={JournalCount}&objectLinkTemplate={Uri.EscapeDataString(JournalObjectLinkTemplate)}&timeOffset={JournalTimeOffset}";
yield return new Uri($"{BaseUrl}/m42Services/api/journalPortal?{query}");
yield return new Uri($"{BaseUrl}/api/journalPortal?{query}");
}
private void CopyIncomingHeaders(HttpRequestMessage request)
{
foreach (var header in Request.Headers)
{
if (string.Equals(header.Key, "Host", StringComparison.OrdinalIgnoreCase)
|| string.Equals(header.Key, "Connection", StringComparison.OrdinalIgnoreCase)
|| string.Equals(header.Key, "Accept-Encoding", StringComparison.OrdinalIgnoreCase))
continue;
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
private static Matrix42.Contracts.Platform.Data.JournalEntryInfo[] DeserializeJournalPortalEntries(string responseText)
{
try
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<Matrix42.Contracts.Platform.Data.JournalEntryInfo[]>(responseText);
}
catch
{
var token = Newtonsoft.Json.Linq.JToken.Parse(responseText);
if (token.Type == Newtonsoft.Json.Linq.JTokenType.Array)
return token.ToObject<Matrix42.Contracts.Platform.Data.JournalEntryInfo[]>();
foreach (var propertyName in new[] { "result", "Result", "value", "Value" })
{
var resultToken = token[propertyName];
if (resultToken != null && resultToken.Type != Newtonsoft.Json.Linq.JTokenType.Null)
return resultToken.ToObject<Matrix42.Contracts.Platform.Data.JournalEntryInfo[]>();
}
return null;
}
}
internal static List<cTicketJournalItem> CreateMissingMethodDiagnostics(string stage, Guid objectId, MissingMethodException ex)
{
var details = BuildMissingMethodDiagnostic(stage, objectId, ex);