fix: invoke journal service compatibly across 26.1 patches

This commit is contained in:
Meik
2026-07-01 00:07:26 +02:00
parent 3d6a8f514c
commit 5acaaa75b4
2 changed files with 124 additions and 5 deletions

View File

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

View File

@@ -1408,15 +1408,15 @@ namespace C4IT.F4SD
{ {
await Task.Delay(0); await Task.Delay(0);
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>(); List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
var entries = F4SDM42WebApiController.defaultInstance.GetJournalService().GetJournalList(activityEOID, false, 0, 50, "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>", 120); var entries = LoadJournalEntries(activityEOID);
LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug); LogEntry($"{entries.Count} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
for (int i = 0; i < entries.Length; i++) for (int i = 0; i < entries.Count; i++)
{ {
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i]; Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
var text = item.Text ?? string.Empty; var text = item.Text ?? string.Empty;
var createdDate = item.CreatedDate ?? DateTime.MinValue; var createdDate = item.CreatedDate ?? DateTime.MinValue;
LogEntry($"Journal entry {i + 1}/{entries.Length}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug); LogEntry($"Journal entry {i + 1}/{entries.Count}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
journalEntries.Add(new cTicketJournalItem() journalEntries.Add(new cTicketJournalItem()
{ {
JournalId = item.Id, JournalId = item.Id,
@@ -1446,6 +1446,125 @@ namespace C4IT.F4SD
} }
} }
private static IReadOnlyList<Matrix42.Contracts.Platform.Data.JournalEntryInfo> LoadJournalEntries(Guid activityEOID)
{
var journalService = F4SDM42WebApiController.defaultInstance.GetJournalService();
var serviceType = journalService.GetType();
var objectLinkTemplate = "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>";
var methods = serviceType
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(IsJournalReaderMethod)
.OrderByDescending(method => method.GetParameters().Length)
.ToList();
foreach (var method in methods)
{
if (!TryBuildJournalListArguments(method, activityEOID, objectLinkTemplate, out var arguments))
continue;
try
{
var result = method.Invoke(journalService, arguments);
if (result is Matrix42.Contracts.Platform.Data.JournalEntryInfo[] arrayResult)
return arrayResult;
if (result is IEnumerable<Matrix42.Contracts.Platform.Data.JournalEntryInfo> enumerableResult)
return enumerableResult.ToList();
throw new MissingMethodException($"IJournalService.GetJournalList returned unsupported type '{result?.GetType().FullName ?? "<null>"}'.");
}
catch (TargetInvocationException ex) when (ex.InnerException != null)
{
throw ex.InnerException;
}
}
throw new MissingMethodException($"No compatible IJournalService.GetJournalList overload was found on '{serviceType.FullName}'. Available overloads: {string.Join("; ", methods.Select(FormatMethodSignature))}");
}
private static bool IsJournalReaderMethod(MethodInfo method)
{
var methodName = method.Name;
if (methodName.Contains("."))
methodName = methodName.Substring(methodName.LastIndexOf(".", StringComparison.Ordinal) + 1);
if (!(methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase) || methodName.StartsWith("Load", StringComparison.OrdinalIgnoreCase)))
return false;
if (!methodName.Contains("Journal", StringComparison.OrdinalIgnoreCase))
return false;
if (!method.GetParameters().Any(parameter => parameter.ParameterType == typeof(Guid)))
return false;
var returnType = method.ReturnType;
if (returnType.IsArray)
return returnType.GetElementType()?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName;
if (returnType.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName)
return true;
return returnType.GetInterfaces()
.Where(type => type.IsGenericType)
.Select(type => type.GetGenericArguments().FirstOrDefault())
.Any(type => type?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName);
}
private static bool TryBuildJournalListArguments(MethodInfo method, Guid activityEOID, string objectLinkTemplate, out object[] arguments)
{
var parameters = method.GetParameters();
arguments = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
var parameterType = parameter.ParameterType;
var parameterName = parameter.Name ?? string.Empty;
var lowerName = parameterName.ToLowerInvariant();
if (parameterType == typeof(Guid))
{
arguments[i] = activityEOID;
}
else if (parameterType == typeof(bool))
{
arguments[i] = false;
}
else if (parameterType == typeof(int))
{
if (lowerName.Contains("time"))
arguments[i] = 120;
else if (lowerName.Contains("count") || lowerName.Contains("take") || lowerName.Contains("limit") || lowerName.Contains("size"))
arguments[i] = 50;
else
arguments[i] = 0;
}
else if (parameterType == typeof(string))
{
arguments[i] = lowerName.Contains("template") || lowerName.Contains("link") ? objectLinkTemplate : null;
}
else if (parameterType == typeof(string[]))
{
arguments[i] = null;
}
else if (parameter.HasDefaultValue)
{
arguments[i] = parameter.DefaultValue;
}
else
{
return false;
}
}
return true;
}
private static string FormatMethodSignature(MethodInfo method)
{
return $"{method.ReturnType.FullName} {method.Name}({string.Join(", ", method.GetParameters().Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}"))})";
}
internal async Task<bool> updateActivitySolution(Guid objectId, string solutionHtml) internal async Task<bool> updateActivitySolution(Guid objectId, string solutionHtml)
{ {