feat: support parallel legacy and sandbox extensions
This commit is contained in:
298
F4SDM42WebApi/F4SDHelperService.UserId.cs
Normal file
298
F4SDM42WebApi/F4SDHelperService.UserId.cs
Normal file
@@ -0,0 +1,298 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
|
||||
using Matrix42.Common;
|
||||
|
||||
using update4u.SPS.DataLayer;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.F4SD
|
||||
{
|
||||
public partial class F4SDHelperService
|
||||
{
|
||||
internal async Task<List<cF4SDTicketSummary>> getTicketListByUser(
|
||||
Guid userId,
|
||||
int hours,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
var method = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(method);
|
||||
try
|
||||
{
|
||||
await Task.Delay(0);
|
||||
if (userId == Guid.Empty)
|
||||
return new List<cF4SDTicketSummary>();
|
||||
|
||||
var activityFilter = GetActivityFilter(userId, hours, ticketAndServiceRequestEnabled(), queueoption, queues);
|
||||
LogEntry($"Generating ticket list for userId '{userId}'. ASQL filter: {activityFilter}", LogLevels.Debug);
|
||||
|
||||
var activityTable = FragmentRequestBase.SimpleLoad(
|
||||
SPSActivityClassBaseID,
|
||||
"[Expression-ObjectID] as EOID, TicketNumber, Subject, Service.ID as ServiceId, Service.Name as ServiceName" +
|
||||
", SUBQUERY(BasicSchemaObjectType as bso, bso.Name, bso.id = base.T(SPSCommonClassBase).TypeID) as ActivityType" +
|
||||
", COALESCE(T(SPSActivityClassIncident).Asset.T(SPSComputerClassBase).Name, T(SPSActivityClassIncident).Asset.T(SPSAssetClassSIMCard).PhoneNumber, T(SPSActivityClassIncident).Asset.Name, T(SPSActivityClassIncident).Asset.objectid) as AssetName" +
|
||||
", SUBQUERY(BasicSchemaObjectType AS t, t.Name, t.ID=base.T(SPSActivityClassIncident).Asset.T(SPSCommonClassBase).TypeID) as AssetCIName",
|
||||
activityFilter);
|
||||
|
||||
if (activityTable?.Rows == null || activityTable.Rows.Count == 0)
|
||||
return new List<cF4SDTicketSummary>();
|
||||
|
||||
var tickets = new List<cF4SDTicketSummary>(activityTable.Rows.Count);
|
||||
foreach (DataRow entry in activityTable.Rows)
|
||||
{
|
||||
var activityId = getGuidFromObject(entry["EOID"]);
|
||||
var ticketNumber = getStringFromObject(entry["TicketNumber"]);
|
||||
var subject = getStringFromObject(entry["Subject"]);
|
||||
if (string.IsNullOrEmpty(ticketNumber) || string.IsNullOrEmpty(subject))
|
||||
continue;
|
||||
|
||||
var state = GetActivityState(activityId);
|
||||
tickets.Add(new cF4SDTicketSummary
|
||||
{
|
||||
TicketObjectId = activityId,
|
||||
Name = ticketNumber,
|
||||
ActivityType = getStringFromObject(entry["ActivityType"]),
|
||||
Summary = subject,
|
||||
StatusId = state.Item1,
|
||||
Status = state.Item2,
|
||||
AssetCIName = getStringFromObject(entry["AssetCIName"]),
|
||||
AssetName = getStringFromObject(entry["AssetName"]),
|
||||
ServiceId = getGuidFromObject(entry["ServiceId"]),
|
||||
ServiceName = getStringFromObject(entry["ServiceName"]),
|
||||
UserId = userId,
|
||||
IsPrimaryAccount = true
|
||||
});
|
||||
}
|
||||
|
||||
return tickets.OrderByDescending(ticket => ticket.Name).ToList();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogException(exception);
|
||||
return new List<cF4SDTicketSummary>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(method);
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<TicketOverviewCountsResult> getTicketOverviewCounts(
|
||||
Guid userId,
|
||||
string scope,
|
||||
IEnumerable<string> keys,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
var method = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(method);
|
||||
try
|
||||
{
|
||||
var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase);
|
||||
var normalizedKeys = (keys ?? Array.Empty<string>())
|
||||
.Where(key => !string.IsNullOrWhiteSpace(key))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
if (normalizedKeys.Count == 0)
|
||||
normalizedKeys.AddRange(TicketOverviewKeys);
|
||||
|
||||
var entries = await LoadTicketOverviewEntries(userId, useRoleScope, queueoption, queues);
|
||||
List<TicketOverviewEntry> unassignedEntries = null;
|
||||
if (!useRoleScope && normalizedKeys.Any(IsUnassignedOverviewKey))
|
||||
unassignedEntries = await LoadTicketOverviewUnassignedEntriesForPersonalScope(userId, queueoption, queues);
|
||||
|
||||
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var key in normalizedKeys)
|
||||
{
|
||||
var source = !useRoleScope && IsUnassignedOverviewKey(key)
|
||||
? unassignedEntries ?? new List<TicketOverviewEntry>()
|
||||
: entries;
|
||||
counts[key] = source.Count(entry => MatchesTicketOverviewKey(entry, key));
|
||||
}
|
||||
|
||||
return new TicketOverviewCountsResult { Counts = counts };
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogException(exception);
|
||||
return new TicketOverviewCountsResult();
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(method);
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles(
|
||||
Guid userId,
|
||||
IEnumerable<Guid> roleGuids,
|
||||
IEnumerable<string> keys,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, roleGuids);
|
||||
return await getTicketOverviewCountsByRoles(null, roleIds, keys, queueoption, queues);
|
||||
}
|
||||
|
||||
internal async Task<List<TicketOverviewRelationDto>> getTicketOverviewRelations(
|
||||
Guid userId,
|
||||
string scope,
|
||||
string key,
|
||||
int count,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
var method = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(method);
|
||||
try
|
||||
{
|
||||
if (userId == Guid.Empty || string.IsNullOrWhiteSpace(key))
|
||||
return new List<TicketOverviewRelationDto>();
|
||||
|
||||
var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase);
|
||||
var entries = !useRoleScope && IsUnassignedOverviewKey(key)
|
||||
? await LoadTicketOverviewUnassignedEntriesForPersonalScope(userId, queueoption, queues)
|
||||
: await LoadTicketOverviewEntries(userId, useRoleScope, queueoption, queues);
|
||||
|
||||
var filtered = entries
|
||||
.Where(entry => MatchesTicketOverviewKey(entry, key))
|
||||
.OrderByDescending(entry => entry.CreatedDate);
|
||||
if (count > 0)
|
||||
filtered = filtered.Take(count).OrderByDescending(entry => entry.CreatedDate);
|
||||
|
||||
return filtered.Select(entry => new TicketOverviewRelationDto
|
||||
{
|
||||
Type = enumF4sdSearchResultClass.Ticket,
|
||||
Name = entry.TicketNumber ?? string.Empty,
|
||||
DisplayName = entry.TicketNumber ?? string.Empty,
|
||||
id = entry.TicketId,
|
||||
Status = enumF4sdSearchResultStatus.Active,
|
||||
Infos = new Dictionary<string, string>
|
||||
{
|
||||
["Summary"] = entry.Summary ?? string.Empty,
|
||||
["StatusId"] = ConvertM42State(entry.State),
|
||||
["ActivityType"] = entry.ActivityType ?? string.Empty,
|
||||
["UserDisplayName"] = entry.InitiatorDisplayName ?? string.Empty,
|
||||
["UserAccount"] = entry.InitiatorAccount ?? string.Empty,
|
||||
["UserDomain"] = entry.InitiatorDomain ?? string.Empty,
|
||||
["UserSid"] = entry.InitiatorSid ?? string.Empty,
|
||||
["Sids"] = entry.InitiatorSid ?? string.Empty,
|
||||
["UserId"] = entry.InitiatorId == Guid.Empty ? string.Empty : entry.InitiatorId.ToString(),
|
||||
["UserGuid"] = entry.InitiatorId == Guid.Empty ? string.Empty : entry.InitiatorId.ToString()
|
||||
},
|
||||
Identities = new List<cF4sdIdentityEntry>
|
||||
{
|
||||
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = entry.TicketId },
|
||||
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = entry.InitiatorId }
|
||||
}
|
||||
}).ToList();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogException(exception);
|
||||
return new List<TicketOverviewRelationDto>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(method);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntries(
|
||||
Guid userId,
|
||||
bool useRoleScope,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
if (userId == Guid.Empty)
|
||||
return new List<TicketOverviewEntry>();
|
||||
|
||||
var filter = await BuildTicketOverviewFilterAsync(userId, useRoleScope, queueoption, queues);
|
||||
return await LoadTicketOverviewEntriesByFilter(filter);
|
||||
}
|
||||
|
||||
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewUnassignedEntriesForPersonalScope(
|
||||
Guid userId,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
if (userId == Guid.Empty)
|
||||
return new List<TicketOverviewEntry>();
|
||||
|
||||
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null);
|
||||
var filter = BuildTicketOverviewFilterForRoleIds(roleIds, null, queueoption, queues);
|
||||
if (string.IsNullOrWhiteSpace(filter))
|
||||
return new List<TicketOverviewEntry>();
|
||||
|
||||
return await LoadTicketOverviewEntriesByFilter(filter + " AND Recipient IS NULL");
|
||||
}
|
||||
|
||||
private async Task<string> BuildTicketOverviewFilterAsync(
|
||||
Guid userId,
|
||||
bool useRoleScope,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
var filter = BuildTicketOverviewBaseFilter(queueoption, queues);
|
||||
if (!useRoleScope)
|
||||
return filter + $" AND (Recipient = '{Escape(userId.ToString("D"))}')";
|
||||
|
||||
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null);
|
||||
return BuildTicketOverviewFilterForRoleIds(roleIds, filter);
|
||||
}
|
||||
|
||||
private async Task<List<Guid>> ResolveTicketOverviewRoleIdsAsync(Guid userId, IEnumerable<Guid> roleGuids)
|
||||
{
|
||||
var roleIds = (roleGuids ?? Enumerable.Empty<Guid>())
|
||||
.Where(id => id != Guid.Empty)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
if (roleIds.Count > 0 || userId == Guid.Empty)
|
||||
return roleIds;
|
||||
|
||||
var roles = await getRoleMembershipById(userId) ?? new List<M42Role>();
|
||||
return roles
|
||||
.Where(role => role != null && role.Id != Guid.Empty)
|
||||
.Select(role => role.Id)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private string GetActivityFilter(
|
||||
Guid userId,
|
||||
int hours,
|
||||
bool ticketAndServiceRequestEnabled,
|
||||
int queueoption,
|
||||
List<cApiM42TicketQueueInfo> queues)
|
||||
{
|
||||
var filter = $"Initiator = '{Escape(userId.ToString("D"))}'";
|
||||
if (ticketAndServiceRequestEnabled)
|
||||
{
|
||||
filter += " AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL" +
|
||||
" OR UsedInTypeSPSActivityTypeTicket IS NOT NULL" +
|
||||
" OR UsedInTypeSPSActivityTypeServiceRequest IS NOT NULL)";
|
||||
}
|
||||
else
|
||||
{
|
||||
filter += " AND UsedInTypeSPSActivityTypeIncident IS NOT NULL";
|
||||
}
|
||||
|
||||
var startDate = AsqlHelper.PrepareDateTime(DateTime.UtcNow.AddHours(-hours), true);
|
||||
var endDate = AsqlHelper.PrepareDateTime(DateTime.UtcNow, true);
|
||||
filter += " AND (T(SPSCommonClassBase).State <> 204" +
|
||||
$" OR (ClosedDate > {startDate} AND ClosedDate < {endDate}))";
|
||||
|
||||
return AppendQueueFilter(filter, queueoption, queues);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user