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> getTicketListByUser( Guid userId, int hours, int queueoption, List queues) { var method = MethodBase.GetCurrentMethod(); LogMethodBegin(method); try { await Task.Delay(0); if (userId == Guid.Empty) return new List(); 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(); var tickets = new List(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(); } finally { LogMethodEnd(method); } } internal async Task getTicketOverviewCounts( Guid userId, string scope, IEnumerable keys, int queueoption, List queues) { var method = MethodBase.GetCurrentMethod(); LogMethodBegin(method); try { var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase); var normalizedKeys = (keys ?? Array.Empty()) .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 unassignedEntries = null; if (!useRoleScope && normalizedKeys.Any(IsUnassignedOverviewKey)) unassignedEntries = await LoadTicketOverviewUnassignedEntriesForPersonalScope(userId, queueoption, queues); var counts = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var key in normalizedKeys) { var source = !useRoleScope && IsUnassignedOverviewKey(key) ? unassignedEntries ?? new List() : entries; counts[key] = CountTicketOverviewEntries(source, key); } return CreateTicketOverviewCountsResult(counts); } catch (Exception exception) { LogException(exception); return new TicketOverviewCountsResult(); } finally { LogMethodEnd(method); } } internal async Task getTicketOverviewCountsByRoles( Guid userId, IEnumerable roleGuids, IEnumerable keys, int queueoption, List queues) { var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, roleGuids); return await getTicketOverviewCountsByRoles(null, roleIds, keys, queueoption, queues); } internal async Task> getTicketOverviewRelations( Guid userId, string scope, string key, int count, int queueoption, List queues) { var method = MethodBase.GetCurrentMethod(); LogMethodBegin(method); try { if (userId == Guid.Empty || string.IsNullOrWhiteSpace(key)) return new List(); 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 { ["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 { 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(); } finally { LogMethodEnd(method); } } private async Task> LoadTicketOverviewEntries( Guid userId, bool useRoleScope, int queueoption, List queues) { if (userId == Guid.Empty) return new List(); var filter = await BuildTicketOverviewFilterAsync(userId, useRoleScope, queueoption, queues); return await LoadTicketOverviewEntriesByFilter(filter); } private async Task> LoadTicketOverviewUnassignedEntriesForPersonalScope( Guid userId, int queueoption, List queues) { if (userId == Guid.Empty) return new List(); var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null); var filter = BuildTicketOverviewFilterForRoleIds(roleIds, null, queueoption, queues); if (string.IsNullOrWhiteSpace(filter)) return new List(); return await LoadTicketOverviewEntriesByFilter(filter + " AND Recipient IS NULL"); } private async Task BuildTicketOverviewFilterAsync( Guid userId, bool useRoleScope, int queueoption, List 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> ResolveTicketOverviewRoleIdsAsync(Guid userId, IEnumerable roleGuids) { var roleIds = (roleGuids ?? Enumerable.Empty()) .Where(id => id != Guid.Empty) .Distinct() .ToList(); if (roleIds.Count > 0 || userId == Guid.Empty) return roleIds; var roles = await getRoleMembershipById(userId) ?? new List(); 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 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); } } }