Files
2025-07-20 15:31:35 +10:00

336 lines
14 KiB
C#

using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Models.Services.Jobs.JobLists;
using Disco.Models.Services.Searching;
using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace Disco.Services.Searching
{
public static class Search
{
#region Jobs
public static List<JobSearchResultItem> SearchJobs(DiscoDataContext Database, string Term, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit)
{
var query = (IQueryable<Job>)Database.Jobs;
string userIdTerm = Term.Contains('\\') ? Term : ActiveDirectory.ParseDomainAccountId(Term);
if (int.TryParse(Term, out var termInt))
{
// Term is a Number (int)
query = query.Where(j =>
j.Id == termInt ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == userIdTerm ||
j.User.DisplayName.Contains(Term));
}
else
{
query = query.Where(j =>
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == userIdTerm ||
j.User.DisplayName.Contains(Term));
}
if (LimitCount.HasValue)
query = query.Take(LimitCount.Value);
return query.Select(j => new
{
Id = j.Id,
DeviceSerialNumber = j.DeviceSerialNumber,
UserId = j.UserId,
UserDisplayName = j.User.DisplayName
}).ToArray().Select(i => new JobSearchResultItem()
{
Id = i.Id.ToString(),
DeviceSerialNumber = i.DeviceSerialNumber,
UserId = i.UserId,
UserDisplayName = i.UserDisplayName
}).OrderByDescending(i => i.ScoreValues.Score(Term)).ToList();
}
public static JobTableModel SearchJobsTable(DiscoDataContext Database, string Term, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit, bool IncludeJobStatus = true, bool SearchDetails = false)
{
var query = default(IQueryable<Job>);
string userIdTerm = Term.Contains('\\') ? Term : ActiveDirectory.ParseDomainAccountId(Term);
if (int.TryParse(Term, out var termInt))
{
// Term is a Number (int)
if (SearchDetails)
{
query = BuildJobTableModel(Database).Where(j =>
j.Id == termInt ||
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term) ||
j.JobLogs.Any(jl => jl.Comments.Contains(Term)) ||
j.JobAttachments.Any(ja => ja.Comments.Contains(Term)) ||
j.JobMetaWarranty.ExternalReference.Contains(Term) ||
j.JobMetaNonWarranty.RepairerReference.Contains(Term) ||
j.JobMetaNonWarranty.PurchaseOrderReference.Contains(Term));
}
else
{
query = BuildJobTableModel(Database).Where(j =>
j.Id == termInt ||
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term));
}
}
else
{
if (SearchDetails)
{
query = BuildJobTableModel(Database).Where(j =>
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term) ||
j.JobLogs.Any(jl => jl.Comments.Contains(Term)) ||
j.JobAttachments.Any(ja => ja.Comments.Contains(Term)) ||
j.JobMetaWarranty.ExternalReference.Contains(Term) ||
j.JobMetaNonWarranty.RepairerReference.Contains(Term) ||
j.JobMetaNonWarranty.PurchaseOrderReference.Contains(Term));
}
else
{
query = BuildJobTableModel(Database).Where(j =>
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term));
}
}
if (LimitCount.HasValue)
query = query.Take(LimitCount.Value);
JobTableModel model = new JobTableModel() { ShowStatus = IncludeJobStatus }
.Fill(Database, query, true)
.Score(Term);
return model;
}
public static IQueryable<Job> BuildJobTableModel(DiscoDataContext Database)
{
return Database.Jobs
.Include(j => j.JobType)
.Include(j => j.Device)
.Include(j => j.User)
.Include(j => j.OpenedTechUser);
}
#endregion
#region Users
public static List<UserSearchResultItem> SearchUsersUpstream(DiscoDataContext Database, string Term, bool PersistResults, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit)
{
return UserService.SearchUsers(Database, Term, PersistResults, LimitCount).Select(u => new UserSearchResultItem()
{
Id = u.UserId,
FriendlyId = u.FriendlyId(),
Surname = u.Surname,
GivenName = u.GivenName,
DisplayName = u.DisplayName,
AssignedDevicesCount = 0,
JobCount = 0,
JobCountOpen = 0,
UserFlagAssignments = null
}).OrderByDescending(i => i.ScoreValues.Score(Term)).ToList();
}
public static List<UserSearchResultItem> SearchUsers(DiscoDataContext Database, string Term, bool PersistResults, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit)
{
if (string.IsNullOrWhiteSpace(Term) || Term.Length < 2)
throw new ArgumentException("Search Term must contain at least two characters", "Term");
// Search Active Directory
var adResults = SearchUsersUpstream(Database, Term, PersistResults, LimitCount);
// Search Database
var dbResults = Database.Users.Where(u =>
u.UserId.Contains(Term) ||
u.Surname.Contains(Term) ||
u.GivenName.Contains(Term) ||
u.DisplayName.Contains(Term))
.ToUserSearchResultItems(null)
.ToList();
IEnumerable<UserSearchResultItem> results;
if (PersistResults)
{
// AD Search persisted the results to the database
results = dbResults;
}
else
{
var adResultsIndexed = adResults.ToDictionary(u => u.Id, StringComparer.OrdinalIgnoreCase);
var dbResultsIndexed = dbResults.ToDictionary(u => u.Id, StringComparer.OrdinalIgnoreCase);
// Update DB Results
dbResults.ForEach(u =>
{
if (adResultsIndexed.TryGetValue(u.Id, out var adResult))
{
u.Surname = adResult.Surname;
u.GivenName = adResult.GivenName;
u.DisplayName = adResult.DisplayName;
}
});
// Add AD Results
var adResultsAdditional = adResults.Where(u => !dbResultsIndexed.ContainsKey(u.Id));
// Join AD & DB Results
results = adResultsAdditional.Concat(dbResults);
}
results = results.OrderByDescending(i => i.ScoreValues.Score(Term));
if (LimitCount.HasValue)
results = results.Take(LimitCount.Value);
return results.ToList();
}
public static List<UserSearchResultItem> SearchUserFlag(DiscoDataContext Database, int UserFlagId)
{
return Database.UserFlagAssignments
.Where(a => a.UserFlagId == UserFlagId && !a.RemovedDate.HasValue)
.Select(a => a.User)
.ToUserSearchResultItems(null);
}
public static List<DeviceSearchResultItem> SearchDeviceFlag(DiscoDataContext Database, int deviceFlagId)
{
return Database.DeviceFlagAssignments
.Where(a => a.DeviceFlagId == deviceFlagId && !a.RemovedDate.HasValue)
.Select(a => a.Device)
.ToDeviceSearchResultItems(null);
}
private static List<UserSearchResultItem> ToUserSearchResultItems(this IQueryable<User> Query, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit)
{
if (LimitCount.HasValue)
Query = Query.Take(LimitCount.Value);
var results = Query.Select(u => new UserSearchResultItem()
{
Id = u.UserId,
Surname = u.Surname,
GivenName = u.GivenName,
DisplayName = u.DisplayName,
AssignedDevicesCount = u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).Count(),
JobCount = u.Jobs.Count(),
JobCountOpen = u.Jobs.Count(j => !j.ClosedDate.HasValue),
UserFlagAssignments = u.UserFlagAssignments
}).ToList();
results.ForEach(u => u.FriendlyId = ActiveDirectory.FriendlyAccountId(u.Id));
return results;
}
#endregion
#region Devices
public static List<DeviceSearchResultItem> SearchDevices(DiscoDataContext Database, string Term, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit, bool SearchDetails = false, bool includeDecommissioned = false)
{
IQueryable<Device> query;
query = null;
if (SearchDetails)
{
query = Database.Devices
.Where(d => includeDecommissioned || d.DecommissionedDate == null)
.Where(d =>
d.AssetNumber.Contains(Term) ||
d.DeviceDomainId.Contains(Term) ||
d.SerialNumber.Contains(Term) ||
d.Location.Contains(Term) ||
Term.Contains(d.SerialNumber) ||
d.DeviceDetails.Any(dd => dd.Value.Contains(Term))
);
}
else
{
query = Database.Devices
.Where(d => includeDecommissioned || d.DecommissionedDate == null)
.Where(d =>
d.AssetNumber.Contains(Term) ||
d.DeviceDomainId.Contains(Term) ||
d.SerialNumber.Contains(Term) ||
d.Location.Contains(Term) ||
Term.Contains(d.SerialNumber)
);
}
return query
.ToDeviceSearchResultItems(LimitCount)
.OrderByDescending(i => i.ScoreValues.Score(Term))
.ToList();
}
public static List<DeviceSearchResultItem> SearchDeviceModel(DiscoDataContext Database, int DeviceModelId)
{
return Database.Devices.Where(d => d.DeviceModelId == DeviceModelId).ToDeviceSearchResultItems(null);
}
public static List<DeviceSearchResultItem> SearchDeviceProfile(DiscoDataContext Database, int DeviceProfileId)
{
return Database.Devices.Where(d => d.DeviceProfileId == DeviceProfileId).ToDeviceSearchResultItems(null);
}
public static List<DeviceSearchResultItem> SearchDeviceBatch(DiscoDataContext Database, int DeviceBatchId)
{
return Database.Devices.Where(d => d.DeviceBatchId == DeviceBatchId).ToDeviceSearchResultItems(null);
}
private static List<DeviceSearchResultItem> ToDeviceSearchResultItems(this IQueryable<Device> Query, int? LimitCount = ActiveDirectory.DefaultSearchResultLimit)
{
if (LimitCount.HasValue)
Query = Query.Take(LimitCount.Value);
return Query.Select(d => new DeviceSearchResultItem()
{
Id = d.SerialNumber,
AssetNumber = d.AssetNumber,
ComputerName = d.DeviceDomainId,
DeviceModelDescription = d.DeviceModel.Description,
DeviceProfileName = d.DeviceProfile.Name,
DeviceBatchName = d.DeviceBatch.Name,
DecommissionedDate = d.DecommissionedDate,
AssignedUserId = d.AssignedUserId,
AssignedUserDisplayName = d.AssignedUser.DisplayName,
JobCount = d.Jobs.Count(),
DeviceFlagAssignments = d.DeviceFlagAssignments,
}).ToList();
}
#endregion
}
}