Files
C4IT-F4SD-M42WebApi/F4SDM42WebApi/F4SDHelperService.UserId.cs

299 lines
13 KiB
C#

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);
}
}
}