299 lines
13 KiB
C#
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] = CountTicketOverviewEntries(source, 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);
|
|
}
|
|
}
|
|
}
|