refactor: make exporting consistent
This commit is contained in:
+112
-93
@@ -1,32 +1,89 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Devices.Exporting;
|
||||
using Disco.Models.Services.Devices;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Plugins.Features.DetailsProvider;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Data;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Disco.Services.Devices.Exporting
|
||||
namespace Disco.Services.Devices
|
||||
{
|
||||
using Metadata = ExportFieldMetadata<DeviceExportRecord>;
|
||||
|
||||
public static class DeviceExport
|
||||
public class DeviceExportContext : IExportContext<DeviceExportOptions, DeviceExportRecord>
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool TimestampSuffix { get; set; }
|
||||
public DeviceExportOptions Options { get; set; }
|
||||
|
||||
public static ExportResult GenerateExport(DiscoDataContext Database, Func<IQueryable<Device>, IQueryable<Device>> Filter, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus)
|
||||
public string SuggestedFilenamePrefix { get; } = "DeviceExport";
|
||||
public string ExcelWorksheetName { get; } = "DeviceExport";
|
||||
public string ExcelTableName { get; } = "Devices";
|
||||
|
||||
[JsonConstructor]
|
||||
private DeviceExportContext()
|
||||
{
|
||||
var deviceQuery = Database.Devices
|
||||
}
|
||||
|
||||
public DeviceExportContext(string name, string description, bool timestampSuffix, DeviceExportOptions options)
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Name = name;
|
||||
Description = description;
|
||||
TimestampSuffix = timestampSuffix;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public DeviceExportContext(DeviceExportOptions options)
|
||||
: this("Device Export", null, true, options)
|
||||
{
|
||||
}
|
||||
|
||||
public ExportResult Export(DiscoDataContext database, IScheduledTaskStatus taskStatus)
|
||||
=> Exporter.Export(database, this, taskStatus);
|
||||
|
||||
private IQueryable<Device> BuildFilteredRecords(DiscoDataContext database)
|
||||
{
|
||||
var query = database.Devices
|
||||
.Include(d => d.AssignedUser.UserDetails)
|
||||
.Include(d => d.DeviceDetails);
|
||||
if (Filter != null)
|
||||
deviceQuery = Filter(deviceQuery);
|
||||
|
||||
switch (Options.ExportType)
|
||||
{
|
||||
case DeviceExportTypes.All:
|
||||
break;
|
||||
case DeviceExportTypes.Batch:
|
||||
if (Options.ExportTypeTargetId.HasValue && Options.ExportTypeTargetId.Value > 0)
|
||||
query = query.Where(d => d.DeviceBatchId != Options.ExportTypeTargetId);
|
||||
else
|
||||
query = query.Where(d => d.DeviceBatchId != null);
|
||||
break;
|
||||
case DeviceExportTypes.Model:
|
||||
query = query.Where(d => d.DeviceModelId == Options.ExportTypeTargetId);
|
||||
break;
|
||||
case DeviceExportTypes.Profile:
|
||||
query = query.Where(d => d.DeviceProfileId == Options.ExportTypeTargetId);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown Device Export Type '{Options.ExportType}'", nameof(Options.ExportType));
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public List<DeviceExportRecord> BuildRecords(DiscoDataContext database, IScheduledTaskStatus taskStatus)
|
||||
{
|
||||
var query = BuildFilteredRecords(database);
|
||||
|
||||
// Update Users
|
||||
if (Options.AssignedUserDisplayName ||
|
||||
@@ -35,13 +92,13 @@ namespace Disco.Services.Devices.Exporting
|
||||
Options.AssignedUserPhoneNumber ||
|
||||
Options.AssignedUserEmailAddress)
|
||||
{
|
||||
TaskStatus.UpdateStatus(5, "Refreshing user details from Active Directory");
|
||||
var userIds = deviceQuery.Where(d => d.AssignedUserId != null).Select(d => d.AssignedUserId).Distinct().ToList();
|
||||
taskStatus.UpdateStatus(5, "Refreshing user details from Active Directory");
|
||||
var userIds = query.Where(d => d.AssignedUserId != null).Select(d => d.AssignedUserId).Distinct().ToList();
|
||||
foreach (var userId in userIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
UserService.GetUser(userId, Database);
|
||||
UserService.GetUser(userId, database);
|
||||
}
|
||||
catch (Exception) { } // Ignore Errors
|
||||
}
|
||||
@@ -50,91 +107,18 @@ namespace Disco.Services.Devices.Exporting
|
||||
// Update Last Network Logon Date
|
||||
if (Options.DeviceLastNetworkLogon)
|
||||
{
|
||||
TaskStatus.UpdateStatus(15, "Refreshing device last network logon dates from Active Directory");
|
||||
taskStatus.UpdateStatus(15, "Refreshing device last network logon dates from Active Directory");
|
||||
try
|
||||
{
|
||||
Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDates(Database, ScheduledTaskMockStatus.Create("UpdateLastNetworkLogonDates"));
|
||||
Database.SaveChanges();
|
||||
Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDates(database, ScheduledTaskMockStatus.Create("UpdateLastNetworkLogonDates"));
|
||||
database.SaveChanges();
|
||||
}
|
||||
catch (Exception) { } // Ignore Errors
|
||||
}
|
||||
|
||||
TaskStatus.UpdateStatus(25, "Extracting records from the database");
|
||||
taskStatus.UpdateStatus(25, "Gathering database records");
|
||||
|
||||
var records = BuildRecords(deviceQuery).ToList();
|
||||
|
||||
// materialize device details
|
||||
records.ForEach(r =>
|
||||
{
|
||||
if (Options.DetailBios)
|
||||
r.DeviceDetailBios = r.DeviceDetails.Bios();
|
||||
if (Options.DetailBaseBoard)
|
||||
r.DeviceDetailBaseBoard = r.DeviceDetails.BaseBoard();
|
||||
if (Options.DetailComputerSystem)
|
||||
r.DeviceDetailComputerSystem = r.DeviceDetails.ComputerSystem();
|
||||
if (Options.DetailProcessors)
|
||||
r.DeviceDetailProcessors = r.DeviceDetails.Processors();
|
||||
if (Options.DetailMemory)
|
||||
r.DeviceDetailPhysicalMemory = r.DeviceDetails.PhysicalMemory();
|
||||
if (Options.DetailDiskDrives)
|
||||
r.DeviceDetailDiskDrives = r.DeviceDetails.DiskDrives();
|
||||
if (Options.DetailLanAdapters || Options.DetailWLanAdapters)
|
||||
{
|
||||
r.DeviceDetailNetworkAdapters = r.DeviceDetails.NetworkAdapters();
|
||||
if (r.DeviceDetailNetworkAdapters == null)
|
||||
{
|
||||
r.DeviceDetailLanMacAddresses = r.DeviceDetails.LanMacAddress()?.Split(';').Select(a => a.Trim()).ToList();
|
||||
r.DeviceDetailWlanMacAddresses = r.DeviceDetails.WLanMacAddress()?.Split(';').Select(a => a.Trim()).ToList();
|
||||
}
|
||||
}
|
||||
if (Options.DetailBatteries)
|
||||
r.DeviceDetailBatteries = r.DeviceDetails.Batteries();
|
||||
|
||||
if (Options.AssignedUserDetailCustom && r.AssignedUser != null)
|
||||
{
|
||||
var detailsService = new DetailsProviderService(Database);
|
||||
r.AssignedUserCustomDetails = detailsService.GetDetails(r.AssignedUser);
|
||||
}
|
||||
});
|
||||
|
||||
TaskStatus.UpdateStatus(70, "Building metadata");
|
||||
var metadata = Options.BuildMetadata(records);
|
||||
|
||||
if (metadata.Count == 0)
|
||||
throw new ArgumentException("At least one export field must be specified", "Options");
|
||||
|
||||
TaskStatus.UpdateStatus(80, $"Formatting {records.Count} records for export");
|
||||
|
||||
return ExportHelpers.WriteExport(Options, TaskStatus, metadata, records);
|
||||
}
|
||||
|
||||
public static ExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus)
|
||||
{
|
||||
switch (Options.ExportType)
|
||||
{
|
||||
case DeviceExportTypes.All:
|
||||
return GenerateExport(Database, null, Options, TaskStatus);
|
||||
case DeviceExportTypes.Batch:
|
||||
if (Options.ExportTypeTargetId.HasValue && Options.ExportTypeTargetId.Value > 0)
|
||||
return GenerateExport(Database, devices => devices.Where(d => d.DeviceBatchId == Options.ExportTypeTargetId), Options, TaskStatus);
|
||||
else
|
||||
return GenerateExport(Database, devices => devices.Where(d => d.DeviceBatchId == null), Options, TaskStatus);
|
||||
case DeviceExportTypes.Model:
|
||||
return GenerateExport(Database, devices => devices.Where(d => d.DeviceModelId == Options.ExportTypeTargetId), Options, TaskStatus);
|
||||
case DeviceExportTypes.Profile:
|
||||
return GenerateExport(Database, devices => devices.Where(d => d.DeviceProfileId == Options.ExportTypeTargetId), Options, TaskStatus);
|
||||
default:
|
||||
throw new ArgumentException(string.Format("Unknown Device Export Type", Options.ExportType.ToString()), "Options");
|
||||
}
|
||||
}
|
||||
public static ExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options)
|
||||
{
|
||||
return GenerateExport(Database, Options, ScheduledTaskMockStatus.Create("Device Export"));
|
||||
}
|
||||
|
||||
private static IEnumerable<DeviceExportRecord> BuildRecords(IQueryable<Device> Devices)
|
||||
{
|
||||
return Devices.Select(d => new DeviceExportRecord()
|
||||
var records = query.Select(d => new DeviceExportRecord()
|
||||
{
|
||||
Device = d,
|
||||
|
||||
@@ -170,10 +154,46 @@ namespace Disco.Services.Devices.Exporting
|
||||
AttachmentsCount = d.DeviceAttachments.Count(),
|
||||
|
||||
DeviceCertificates = d.DeviceCertificates.Where(dc => dc.Enabled).OrderByDescending(dc => dc.AllocatedDate)
|
||||
}).ToList();
|
||||
|
||||
// materialize device details
|
||||
records.ForEach(r =>
|
||||
{
|
||||
if (Options.DetailBios)
|
||||
r.DeviceDetailBios = r.DeviceDetails.Bios();
|
||||
if (Options.DetailBaseBoard)
|
||||
r.DeviceDetailBaseBoard = r.DeviceDetails.BaseBoard();
|
||||
if (Options.DetailComputerSystem)
|
||||
r.DeviceDetailComputerSystem = r.DeviceDetails.ComputerSystem();
|
||||
if (Options.DetailProcessors)
|
||||
r.DeviceDetailProcessors = r.DeviceDetails.Processors();
|
||||
if (Options.DetailMemory)
|
||||
r.DeviceDetailPhysicalMemory = r.DeviceDetails.PhysicalMemory();
|
||||
if (Options.DetailDiskDrives)
|
||||
r.DeviceDetailDiskDrives = r.DeviceDetails.DiskDrives();
|
||||
if (Options.DetailLanAdapters || Options.DetailWLanAdapters)
|
||||
{
|
||||
r.DeviceDetailNetworkAdapters = r.DeviceDetails.NetworkAdapters();
|
||||
if (r.DeviceDetailNetworkAdapters == null)
|
||||
{
|
||||
r.DeviceDetailLanMacAddresses = r.DeviceDetails.LanMacAddress()?.Split(';').Select(a => a.Trim()).ToList();
|
||||
r.DeviceDetailWlanMacAddresses = r.DeviceDetails.WLanMacAddress()?.Split(';').Select(a => a.Trim()).ToList();
|
||||
}
|
||||
}
|
||||
if (Options.DetailBatteries)
|
||||
r.DeviceDetailBatteries = r.DeviceDetails.Batteries();
|
||||
|
||||
if (Options.AssignedUserDetailCustom && r.AssignedUser != null)
|
||||
{
|
||||
var detailsService = new DetailsProviderService(database);
|
||||
r.AssignedUserCustomDetails = detailsService.GetDetails(r.AssignedUser);
|
||||
}
|
||||
});
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
private static List<Metadata> BuildMetadata(this DeviceExportOptions options, List<DeviceExportRecord> records)
|
||||
public List<Metadata> BuildMetadata(DiscoDataContext database, List<DeviceExportRecord> records, IScheduledTaskStatus taskStatus)
|
||||
{
|
||||
var processorMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailProcessors?.Count ?? 0));
|
||||
var memoryMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailPhysicalMemory?.Count ?? 0));
|
||||
@@ -184,7 +204,7 @@ namespace Disco.Services.Devices.Exporting
|
||||
var batteriesMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailBatteries?.Count ?? 0));
|
||||
|
||||
IEnumerable<string> assignedUserDetailCustomKeys = null;
|
||||
if (options.AssignedUserDetailCustom)
|
||||
if (Options.AssignedUserDetailCustom)
|
||||
assignedUserDetailCustomKeys = records.Where(r => r.AssignedUserCustomDetails != null).SelectMany(r => r.AssignedUserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
var allAccessors = BuildRecordAccessors(processorMaxCount, memoryMaxCount, diskDriveMaxCount, lanAdapterMaxCount, wlanAdapterMaxCount, certificateMaxCount, batteriesMaxCount, assignedUserDetailCustomKeys);
|
||||
@@ -196,7 +216,7 @@ namespace Disco.Services.Devices.Exporting
|
||||
property = p,
|
||||
details = (DisplayAttribute)p.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault()
|
||||
})
|
||||
.Where(p => p.details != null && (bool)p.property.GetValue(options))
|
||||
.Where(p => p.details != null && (bool)p.property.GetValue(Options))
|
||||
.SelectMany(p =>
|
||||
{
|
||||
var fieldMetadata = allAccessors[p.property.Name];
|
||||
@@ -460,6 +480,5 @@ namespace Disco.Services.Devices.Exporting
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+42
-33
@@ -2,9 +2,11 @@
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Services.Devices.DeviceFlag;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Plugins.Features.DetailsProvider;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
@@ -15,57 +17,67 @@ namespace Disco.Services.Devices.DeviceFlags
|
||||
{
|
||||
using Metadata = ExportFieldMetadata<DeviceFlagExportRecord>;
|
||||
|
||||
public class DeviceFlagExport
|
||||
public class DeviceFlagExportContext : IExportContext<DeviceFlagExportOptions, DeviceFlagExportRecord>
|
||||
{
|
||||
private readonly DiscoDataContext database;
|
||||
private readonly DeviceFlagExportOptions options;
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool TimestampSuffix { get; set; }
|
||||
public DeviceFlagExportOptions Options { get; set; }
|
||||
|
||||
public DeviceFlagExport(DiscoDataContext database, DeviceFlagExportOptions options)
|
||||
public string SuggestedFilenamePrefix { get; } = "DeviceFlagExport";
|
||||
public string ExcelWorksheetName { get; } = "DeviceFlagExport";
|
||||
public string ExcelTableName { get; } = "DeviceFlags";
|
||||
|
||||
[JsonConstructor]
|
||||
private DeviceFlagExportContext()
|
||||
{
|
||||
this.database = database;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public ExportResult Generate(IScheduledTaskStatus status)
|
||||
public DeviceFlagExportContext(string name, string description, bool timestampSuffix, DeviceFlagExportOptions options)
|
||||
{
|
||||
var records = BuildRecords(status);
|
||||
|
||||
var metadata = BuildMetadata(records, status);
|
||||
|
||||
if (metadata.Count == 0)
|
||||
throw new ArgumentException("At least one export field must be specified", nameof(options));
|
||||
|
||||
status.UpdateStatus(90, $"Formatting {records.Count} records for export");
|
||||
return ExportHelpers.WriteExport(options, status, metadata, records);
|
||||
Id = Guid.NewGuid();
|
||||
Name = name;
|
||||
Description = description;
|
||||
TimestampSuffix = timestampSuffix;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
private List<DeviceFlagExportRecord> BuildRecords(IScheduledTaskStatus status)
|
||||
public DeviceFlagExportContext(DeviceFlagExportOptions options)
|
||||
: this("Device Flag Export", null, true, options)
|
||||
{
|
||||
}
|
||||
|
||||
public ExportResult Export(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
=> Exporter.Export(database, this, status);
|
||||
|
||||
public List<DeviceFlagExportRecord> BuildRecords(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
{
|
||||
var query = database.DeviceFlagAssignments
|
||||
.Include(a => a.DeviceFlag);
|
||||
|
||||
if (options.HasDeviceOptions())
|
||||
if (Options.HasDeviceOptions())
|
||||
query = query.Include(a => a.Device);
|
||||
if (options.HasDeviceModelOptions())
|
||||
if (Options.HasDeviceModelOptions())
|
||||
query = query.Include(a => a.Device.DeviceModel);
|
||||
if (options.HasDeviceBatchOptions())
|
||||
if (Options.HasDeviceBatchOptions())
|
||||
query = query.Include(a => a.Device.DeviceBatch);
|
||||
if (options.HasDeviceProfileOptions())
|
||||
if (Options.HasDeviceProfileOptions())
|
||||
query = query.Include(a => a.Device.DeviceProfile);
|
||||
if (options.HasAssignedUserOptions())
|
||||
if (Options.HasAssignedUserOptions())
|
||||
query = query.Include(a => a.Device.AssignedUser);
|
||||
if (options.AssignedUserDetailCustom)
|
||||
if (Options.AssignedUserDetailCustom)
|
||||
query = query.Include(a => a.Device.AssignedUser.UserDetails);
|
||||
|
||||
query = query.Where(a => options.DeviceFlagIds.Contains(a.DeviceFlagId));
|
||||
query = query.Where(a => Options.DeviceFlagIds.Contains(a.DeviceFlagId));
|
||||
|
||||
if (options.CurrentOnly)
|
||||
if (Options.CurrentOnly)
|
||||
{
|
||||
query = query.Where(a => !a.RemovedDate.HasValue);
|
||||
}
|
||||
|
||||
// Update Users
|
||||
if (options.HasAssignedUserOptions())
|
||||
if (Options.HasAssignedUserOptions())
|
||||
{
|
||||
status.UpdateStatus(5, "Refreshing user details from Active Directory");
|
||||
var userIds = query.Where(d => d.Device.AssignedUserId != null).Select(d => d.Device.AssignedUserId).Distinct().ToList();
|
||||
@@ -86,7 +98,7 @@ namespace Disco.Services.Devices.DeviceFlags
|
||||
Assignment = a
|
||||
}).ToList();
|
||||
|
||||
if (options.AssignedUserDetailCustom)
|
||||
if (Options.AssignedUserDetailCustom)
|
||||
{
|
||||
status.UpdateStatus(50, "Extracting custom user detail records");
|
||||
|
||||
@@ -108,12 +120,10 @@ namespace Disco.Services.Devices.DeviceFlags
|
||||
return records;
|
||||
}
|
||||
|
||||
private List<Metadata> BuildMetadata(List<DeviceFlagExportRecord> records, IScheduledTaskStatus status)
|
||||
public List<Metadata> BuildMetadata(DiscoDataContext database, List<DeviceFlagExportRecord> records, IScheduledTaskStatus status)
|
||||
{
|
||||
status.UpdateStatus(80, "Building metadata");
|
||||
|
||||
IEnumerable<string> userDetailCustomKeys = null;
|
||||
if (options.AssignedUserDetailCustom)
|
||||
if (Options.AssignedUserDetailCustom)
|
||||
userDetailCustomKeys = records.Where(r => r.AssignedUserCustomDetails != null).SelectMany(r => r.AssignedUserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
var accessors = BuildAccessors(userDetailCustomKeys);
|
||||
@@ -125,7 +135,7 @@ namespace Disco.Services.Devices.DeviceFlags
|
||||
property = p,
|
||||
details = (DisplayAttribute)p.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault()
|
||||
})
|
||||
.Where(p => p.details != null && p.property.Name != nameof(options.CurrentOnly) && (bool)p.property.GetValue(options))
|
||||
.Where(p => p.details != null && p.property.Name != nameof(Options.CurrentOnly) && (bool)p.property.GetValue(Options))
|
||||
.SelectMany(p =>
|
||||
{
|
||||
var fieldMetadata = accessors[p.property.Name];
|
||||
@@ -224,6 +234,5 @@ namespace Disco.Services.Devices.DeviceFlags
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Services.Devices.DeviceFlag;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Disco.Services.Devices.DeviceFlags
|
||||
{
|
||||
public class DeviceFlagExportTask : ScheduledTask
|
||||
{
|
||||
private const string JobDataMapContext = "Context";
|
||||
|
||||
public override string TaskName { get; } = "Export Device Flags";
|
||||
public override bool SingleInstanceTask { get { return false; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
|
||||
public static ExportTaskContext<DeviceFlagExportOptions> ScheduleNow(DeviceFlagExportOptions options)
|
||||
{
|
||||
// Build Context
|
||||
var context = new ExportTaskContext<DeviceFlagExportOptions>(options);
|
||||
|
||||
// Build Data Map
|
||||
var task = new DeviceFlagExportTask();
|
||||
JobDataMap taskData = new JobDataMap() { { JobDataMapContext, context } };
|
||||
|
||||
// Schedule Task
|
||||
context.TaskStatus = task.ScheduleTask(taskData);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
var context = (ExportTaskContext<DeviceFlagExportOptions>)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext];
|
||||
|
||||
Status.UpdateStatus(10, "Exporting Device Flag Records", "Starting...");
|
||||
|
||||
using (DiscoDataContext Database = new DiscoDataContext())
|
||||
{
|
||||
var export = new DeviceFlagExport(Database, context.Options);
|
||||
|
||||
context.Result = export.Generate(Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using Disco.Models.Services.Devices.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Exporting;
|
||||
|
||||
namespace Disco.Services.Devices.Exporting
|
||||
{
|
||||
public class DeviceExportTask : ScheduledTask
|
||||
{
|
||||
private const string JobDataMapContext = "Context";
|
||||
|
||||
public override string TaskName { get { return "Export Devices"; } }
|
||||
public override bool SingleInstanceTask { get { return false; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
|
||||
public static ExportTaskContext<DeviceExportOptions> ScheduleNow(DeviceExportOptions Options)
|
||||
{
|
||||
// Build Context
|
||||
var context = new ExportTaskContext<DeviceExportOptions>(Options);
|
||||
|
||||
// Build Data Map
|
||||
var task = new DeviceExportTask();
|
||||
JobDataMap taskData = new JobDataMap() { { JobDataMapContext, context} };
|
||||
|
||||
// Schedule Task
|
||||
context.TaskStatus = task.ScheduleTask(taskData);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
var context = (ExportTaskContext<DeviceExportOptions>)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext];
|
||||
|
||||
Status.UpdateStatus(10, "Exporting Device Records", "Starting...");
|
||||
|
||||
using (DiscoDataContext Database = new DiscoDataContext())
|
||||
{
|
||||
context.Result = DeviceExport.GenerateExport(Database, context.Options, Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,6 +347,7 @@
|
||||
<Compile Include="Devices\DeviceDataStoreExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceDetailExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagExportContext.cs" />
|
||||
<Compile Include="Devices\DeviceModelExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceBatchUpdatesHub.cs" />
|
||||
@@ -357,18 +358,16 @@
|
||||
<Compile Include="Devices\Enrolment\EnrolmentTypes.cs" />
|
||||
<Compile Include="Devices\Enrolment\LogMacAddressImportingTask.cs" />
|
||||
<Compile Include="Devices\Enrolment\MacDeviceEnrolment.cs" />
|
||||
<Compile Include="Devices\Exporting\DeviceExport.cs" />
|
||||
<Compile Include="Devices\Exporting\DeviceExportTask.cs" />
|
||||
<Compile Include="Devices\DeviceExportContext.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\Cache.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagExport.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagExportTask.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagsBulkAssignTask.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagsDeleteTask.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagService.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagDeviceAssignedUsersManagedGroup.cs" />
|
||||
<Compile Include="Devices\DeviceFlags\DeviceFlagDevicesManagedGroup.cs" />
|
||||
<Compile Include="Exporting\ExportHelpers.cs" />
|
||||
<Compile Include="Exporting\Exporter.cs" />
|
||||
<Compile Include="Exporting\ExportTask.cs" />
|
||||
<Compile Include="Exporting\ExportTaskContext.cs" />
|
||||
<Compile Include="Devices\Importing\BaseDeviceImportContext.cs" />
|
||||
<Compile Include="Devices\Importing\CsvDeviceImportDataReader.cs" />
|
||||
@@ -425,6 +424,7 @@
|
||||
<Compile Include="Documents\ManagedGroups\DocumentTemplateManagedGroups.cs" />
|
||||
<Compile Include="Documents\ManagedGroups\DocumentTemplateUsersManagedGroup.cs" />
|
||||
<Compile Include="Documents\QRCodeBinaryEncoder.cs" />
|
||||
<Compile Include="Exporting\IExportContext.cs" />
|
||||
<Compile Include="Expressions\EvaluateExpressionParseException.cs" />
|
||||
<Compile Include="Expressions\EvaluateExpressionPart.cs" />
|
||||
<Compile Include="Expressions\Expression.cs" />
|
||||
@@ -491,8 +491,7 @@
|
||||
<Compile Include="Interop\VicEduDept\VicSmart.cs" />
|
||||
<Compile Include="Interop\DiscoServices\UpdateQuery.cs" />
|
||||
<Compile Include="Interop\DiscoServices\UpdateQueryTask.cs" />
|
||||
<Compile Include="Jobs\Exporting\JobExport.cs" />
|
||||
<Compile Include="Jobs\Exporting\JobExportTask.cs" />
|
||||
<Compile Include="Jobs\JobExportContext.cs" />
|
||||
<Compile Include="Jobs\JobActionExtensions.cs" />
|
||||
<Compile Include="Jobs\JobExtensions.cs" />
|
||||
<Compile Include="Jobs\JobFlagExtensions.cs" />
|
||||
@@ -512,7 +511,7 @@
|
||||
<Compile Include="Jobs\Statistics\DailyOpenedClosed.cs" />
|
||||
<Compile Include="Logging\LogBase.cs" />
|
||||
<Compile Include="Logging\LogContext.cs" />
|
||||
<Compile Include="Logging\LogExport.cs" />
|
||||
<Compile Include="Logging\LogExportContext.cs" />
|
||||
<Compile Include="Logging\LogReInitalizeJob.cs" />
|
||||
<Compile Include="Logging\Models\LogEvent.cs" />
|
||||
<Compile Include="Logging\Models\LogEventType.cs" />
|
||||
@@ -600,8 +599,7 @@
|
||||
<Compile Include="Users\Contact\UserContactService.cs" />
|
||||
<Compile Include="Users\UserExtensions.cs" />
|
||||
<Compile Include="Users\UserFlags\Cache.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagExport.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagExportTask.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagExportContext.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagExtensions.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagUserDevicesManagedGroup.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagUsersManagedGroup.cs" />
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Disco.Services.Exporting
|
||||
{
|
||||
public class ExportTask : ScheduledTask
|
||||
{
|
||||
private IExportContext context;
|
||||
public override string TaskName { get => context?.Name ?? "Exporting"; }
|
||||
public override bool SingleInstanceTask { get { return false; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
|
||||
public static ExportTaskContext ScheduleNow(IExportContext exportContext)
|
||||
{
|
||||
// Build Context
|
||||
var taskContext = new ExportTaskContext(exportContext);
|
||||
|
||||
// Build Data Map
|
||||
var task = new ExportTask();
|
||||
JobDataMap taskData = new JobDataMap() { { nameof(ExportTask), taskContext } };
|
||||
|
||||
// Schedule Task
|
||||
taskContext.TaskStatus = task.ScheduleTask(taskData);
|
||||
|
||||
return taskContext;
|
||||
}
|
||||
|
||||
private static string GetCacheKey(Guid exportId) => $"ExportTask_{exportId}";
|
||||
|
||||
public static ExportTaskContext ScheduleNowCacheResult(IExportContext exportContext, Func<Guid, string> returnUrlBuilder)
|
||||
{
|
||||
var taskContext = ScheduleNow(exportContext);
|
||||
|
||||
var key = GetCacheKey(taskContext.Id);
|
||||
HttpRuntime.Cache.Insert(key, taskContext, null, DateTime.Now.AddMinutes(60), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null);
|
||||
|
||||
taskContext.TaskStatus.SetFinishedUrl(returnUrlBuilder(taskContext.Id));
|
||||
|
||||
return taskContext;
|
||||
}
|
||||
|
||||
public static bool TryFromCache(Guid? exportId, out ExportTaskContext exportContext)
|
||||
{
|
||||
if (exportId != null)
|
||||
{
|
||||
var key = GetCacheKey(exportId.Value);
|
||||
|
||||
if (HttpRuntime.Cache.Get(key) is ExportTaskContext context)
|
||||
{
|
||||
exportContext = context;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
exportContext = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
var context = (ExportTaskContext)ExecutionContext.JobDetail.JobDataMap[nameof(ExportTask)];
|
||||
this.context = context.ExportContext;
|
||||
|
||||
Status.UpdateStatus(0, "Exporting", "Starting...");
|
||||
|
||||
using (var database = new DiscoDataContext())
|
||||
{
|
||||
context.Result = context.ExportContext.Export(database, Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
using System;
|
||||
|
||||
namespace Disco.Services.Exporting
|
||||
{
|
||||
public class ExportTaskContext<T> where T : IExportOptions
|
||||
public class ExportTaskContext
|
||||
{
|
||||
public T Options { get; private set; }
|
||||
public IExportContext ExportContext { get; }
|
||||
public ScheduledTaskStatus TaskStatus { get; internal set; }
|
||||
public ExportResult Result { get; internal set; }
|
||||
|
||||
public ScheduledTaskStatus TaskStatus { get; set; }
|
||||
public Guid Id => ExportContext.Id;
|
||||
|
||||
public ExportResult Result { get; set; }
|
||||
|
||||
public ExportTaskContext(T Options)
|
||||
public ExportTaskContext(IExportContext context)
|
||||
{
|
||||
this.Options = Options;
|
||||
ExportContext = context;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using ClosedXML.Excel;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
@@ -9,43 +10,66 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Services
|
||||
namespace Disco.Services.Exporting
|
||||
{
|
||||
internal class ExportHelpers
|
||||
public static class Exporter
|
||||
{
|
||||
public static ExportResult WriteExport<T>(IExportOptions options, IScheduledTaskStatus status, List<ExportFieldMetadata<T>> metadata, List<T> records) where T : IExportRecord
|
||||
public static ExportResult Export<T, R>(DiscoDataContext database, IExportContext<T, R> context, IScheduledTaskStatus status)
|
||||
where T : IExportOptions, new()
|
||||
where R : IExportRecord
|
||||
{
|
||||
var filenameWithoutExtension = $"{options.FilenamePrefix}-{status.StartedTimestamp.Value:yyyyMMdd-HHmmss}";
|
||||
MemoryStream stream;
|
||||
string filename;
|
||||
string mimeType;
|
||||
|
||||
switch (options.Format)
|
||||
status.UpdateStatus(1, $"Exporting {context.Name}", "Gathering data");
|
||||
|
||||
var records = context.BuildRecords(database, status);
|
||||
|
||||
status.UpdateStatus(70, "Building metadata");
|
||||
|
||||
var metadata = context.BuildMetadata(database, records, status);
|
||||
|
||||
if (metadata.Count == 0)
|
||||
throw new ArgumentException("At least one export field must be specified", nameof(context.Options));
|
||||
|
||||
var filenameBuilder = new StringBuilder();
|
||||
filenameBuilder.Append(context.SuggestedFilenamePrefix);
|
||||
if (context.TimestampSuffix)
|
||||
{
|
||||
filenameBuilder.Append('-');
|
||||
filenameBuilder.Append(status.StartedTimestamp.Value.ToString("yyyyMMdd-HHmmss"));
|
||||
}
|
||||
|
||||
status.UpdateStatus(80, $"Rendering {records.Count} records for export");
|
||||
|
||||
switch (context.Options.Format)
|
||||
{
|
||||
case ExportFormat.Csv:
|
||||
stream = WriteCSV(filenameWithoutExtension, metadata, records, out filename, out mimeType);
|
||||
filenameBuilder.Append(".csv");
|
||||
mimeType = "text/csv";
|
||||
stream = WriteCSV(metadata, records);
|
||||
break;
|
||||
case ExportFormat.Xlsx:
|
||||
stream = WriteXlsx(filenameWithoutExtension, options.ExcelWorksheetName, options.ExcelTableName, metadata, records, out filename, out mimeType);
|
||||
filenameBuilder.Append(".xlsx");
|
||||
mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
stream = WriteXlsx(context.ExcelWorksheetName, context.ExcelTableName, metadata, records);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"Unsupported export format: {options.Format}");
|
||||
throw new NotSupportedException($"Unsupported export format: {context.Options.Format}");
|
||||
}
|
||||
|
||||
return new ExportResult()
|
||||
{
|
||||
Result = stream,
|
||||
RecordCount = records.Count,
|
||||
Filename = filename,
|
||||
Filename = filenameBuilder.ToString(),
|
||||
MimeType = mimeType,
|
||||
};
|
||||
}
|
||||
|
||||
private static MemoryStream WriteCSV<T>(string filenameWithoutExtension, List<ExportFieldMetadata<T>> metadata, List<T> records, out string filename, out string mimeType) where T : IExportRecord
|
||||
private static MemoryStream WriteCSV<T>(List<ExportFieldMetadata<T>> metadata, List<T> records) where T : IExportRecord
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
mimeType = "text/csv";
|
||||
filename = $"{filenameWithoutExtension}.csv";
|
||||
|
||||
using (StreamWriter writer = new StreamWriter(stream, Encoding.Default, 0x400, true))
|
||||
{
|
||||
@@ -74,11 +98,9 @@ namespace Disco.Services
|
||||
return stream;
|
||||
}
|
||||
|
||||
private static MemoryStream WriteXlsx<T>(string filenameWithoutExtension, string worksheetName, string tableName, List<ExportFieldMetadata<T>> metadata, List<T> records, out string filename, out string mimeType) where T : IExportRecord
|
||||
private static MemoryStream WriteXlsx<T>(string worksheetName, string tableName, List<ExportFieldMetadata<T>> metadata, List<T> records) where T : IExportRecord
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
filename = $"{filenameWithoutExtension}.xlsx";
|
||||
|
||||
// Create DataTable
|
||||
var dataTable = new DataTable();
|
||||
@@ -0,0 +1,39 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Disco.Services.Exporting
|
||||
{
|
||||
public interface IExportContext
|
||||
{
|
||||
Guid Id { get; set; }
|
||||
string Name { get; set; }
|
||||
string Description { get; set; }
|
||||
|
||||
ExportResult Export(DiscoDataContext database, IScheduledTaskStatus status);
|
||||
}
|
||||
|
||||
public interface IExportContext<T, R>
|
||||
: IExportContext
|
||||
where T : IExportOptions, new()
|
||||
where R : IExportRecord
|
||||
{
|
||||
bool TimestampSuffix { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
string SuggestedFilenamePrefix { get; }
|
||||
[JsonIgnore]
|
||||
string ExcelWorksheetName { get; }
|
||||
[JsonIgnore]
|
||||
string ExcelTableName { get; }
|
||||
|
||||
T Options { get; set; }
|
||||
|
||||
List<R> BuildRecords(DiscoDataContext database, IScheduledTaskStatus status);
|
||||
List<ExportFieldMetadata<R>> BuildMetadata(DiscoDataContext database, List<R> records, IScheduledTaskStatus status);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Services.Jobs.Exporting;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Disco.Services.Jobs.Exporting
|
||||
{
|
||||
public class JobExportTask : ScheduledTask
|
||||
{
|
||||
private const string JobDataMapContext = "Context";
|
||||
|
||||
public override string TaskName { get { return "Export Jobs"; } }
|
||||
public override bool SingleInstanceTask { get { return false; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
|
||||
public static ExportTaskContext<JobExportOptions> ScheduleNow(JobExportOptions Options)
|
||||
{
|
||||
// Build Context
|
||||
var context = new ExportTaskContext<JobExportOptions>(Options);
|
||||
|
||||
// Build Data Map
|
||||
var task = new JobExportTask();
|
||||
JobDataMap taskData = new JobDataMap() { { JobDataMapContext, context} };
|
||||
|
||||
// Schedule Task
|
||||
context.TaskStatus = task.ScheduleTask(taskData);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
var context = (ExportTaskContext<JobExportOptions>)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext];
|
||||
|
||||
Status.UpdateStatus(10, "Exporting Job Records", "Starting...");
|
||||
|
||||
using (DiscoDataContext Database = new DiscoDataContext())
|
||||
{
|
||||
context.Result = JobExport.GenerateExport(Database, context.Options, Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+142
-133
@@ -2,41 +2,131 @@
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Models.Services.Jobs.Exporting;
|
||||
using Disco.Models.Services.Jobs;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Jobs.JobQueues;
|
||||
using Disco.Services.Plugins.Features.DetailsProvider;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.Services.Jobs.Exporting
|
||||
namespace Disco.Services.Jobs
|
||||
{
|
||||
using Metadata = ExportFieldMetadata<JobExportRecord>;
|
||||
|
||||
public static class JobExport
|
||||
public class JobExportContext : IExportContext<JobExportOptions, JobExportRecord>
|
||||
{
|
||||
public static ExportResult GenerateExport(DiscoDataContext database, Func<IQueryable<Job>, IQueryable<Job>> filter, JobExportOptions options, IScheduledTaskStatus taskStatus)
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool TimestampSuffix { get; set; }
|
||||
public JobExportOptions Options { get; set; }
|
||||
|
||||
public string SuggestedFilenamePrefix { get; } = "JobExport";
|
||||
public string ExcelWorksheetName { get; } = "JobExport";
|
||||
public string ExcelTableName { get; } = "Jobs";
|
||||
|
||||
[JsonConstructor]
|
||||
private JobExportContext()
|
||||
{
|
||||
}
|
||||
|
||||
public JobExportContext(string name, string description, bool timestampSuffix, JobExportOptions options)
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Name = name;
|
||||
Description = description;
|
||||
TimestampSuffix = timestampSuffix;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public JobExportContext(JobExportOptions options)
|
||||
: this("Job Export", null, true, options)
|
||||
{
|
||||
}
|
||||
|
||||
public ExportResult Export(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
=> Exporter.Export(database, this, status);
|
||||
|
||||
private IQueryable<Job> BuildFilteredRecords(DiscoDataContext database)
|
||||
{
|
||||
var o = Options;
|
||||
|
||||
var q = database.Jobs.Where(j => j.OpenedDate >= o.FilterStartDate);
|
||||
if (o.FilterEndDate.HasValue)
|
||||
q = q.Where(j => j.OpenedDate <= o.FilterEndDate);
|
||||
|
||||
if (o.FilterJobTypeId != null)
|
||||
q = q.Where(j => j.JobTypeId == o.FilterJobTypeId);
|
||||
|
||||
if (o.FilterJobSubTypeIds?.Any() ?? false)
|
||||
q = q.Where(j => j.JobSubTypes.Any(st => o.FilterJobSubTypeIds.Contains(st.Id)));
|
||||
|
||||
if (o.FilterJobQueueId.HasValue)
|
||||
q = q.Where(j => j.JobQueues.Any(jq => !jq.RemovedDate.HasValue && jq.JobQueueId == o.FilterJobQueueId));
|
||||
|
||||
if (o.FilterJobStatusId != null)
|
||||
{
|
||||
if (o.FilterJobStatusId != Job.JobStatusIds.Closed)
|
||||
q = q.Where(j => j.ClosedDate == null);
|
||||
|
||||
switch (o.FilterJobStatusId)
|
||||
{
|
||||
case Job.JobStatusIds.Open:
|
||||
// already filtered
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingAccountingPayment:
|
||||
q = q.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.AccountingChargeAddedDate != null && j.JobMetaNonWarranty.AccountingChargePaidDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingAccountingCharge:
|
||||
q = q.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.AccountingChargeRequiredDate == null && (j.JobMetaNonWarranty.AccountingChargePaidDate != null || j.JobMetaNonWarranty.AccountingChargeAddedDate != null));
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingDeviceReturn:
|
||||
q = q.Where(j => j.DeviceReadyForReturn != null && j.DeviceReturnedDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingInsuranceProcessing:
|
||||
q = q.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.IsInsuranceClaim && j.JobMetaInsurance.ClaimFormSentDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingRepairs:
|
||||
q = q.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.RepairerLoggedDate != null && j.JobMetaNonWarranty.RepairerCompletedDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingUserAction:
|
||||
q = q.Where(j => j.WaitingForUserAction != null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingWarrantyRepair:
|
||||
q = q.Where(j => j.JobTypeId == JobType.JobTypeIds.HWar && j.JobMetaWarranty.ExternalLoggedDate != null && j.JobMetaWarranty.ExternalCompletedDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.Closed:
|
||||
q = q.Where(j => j.ClosedDate != null);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown Job Status Id: {o.FilterJobStatusId}", nameof(o.FilterJobStatusId));
|
||||
}
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public List<JobExportRecord> BuildRecords(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
{
|
||||
database.Configuration.LazyLoadingEnabled = false;
|
||||
database.Configuration.ProxyCreationEnabled = false;
|
||||
|
||||
var jobQuery = (IQueryable<Job>)database.Jobs;
|
||||
if (filter != null)
|
||||
jobQuery = filter(jobQuery);
|
||||
var query = BuildFilteredRecords(database);
|
||||
|
||||
// Update Users
|
||||
if (options.UserDisplayName ||
|
||||
options.UserSurname ||
|
||||
options.UserGivenName ||
|
||||
options.UserPhoneNumber ||
|
||||
options.UserEmailAddress)
|
||||
if (Options.UserDisplayName ||
|
||||
Options.UserSurname ||
|
||||
Options.UserGivenName ||
|
||||
Options.UserPhoneNumber ||
|
||||
Options.UserEmailAddress)
|
||||
{
|
||||
taskStatus.UpdateStatus(5, "Refreshing user details from Active Directory");
|
||||
var userIds = jobQuery.Where(d => d.UserId != null).Select(d => d.UserId).Distinct().ToList();
|
||||
status.UpdateStatus(5, "Refreshing user details from Active Directory");
|
||||
var userIds = query.Where(d => d.UserId != null).Select(d => d.UserId).Distinct().ToList();
|
||||
foreach (var userId in userIds)
|
||||
{
|
||||
try
|
||||
@@ -48,9 +138,9 @@ namespace Disco.Services.Jobs.Exporting
|
||||
}
|
||||
|
||||
// Update Last Network Logon Date
|
||||
if (options.DeviceLastNetworkLogon)
|
||||
if (Options.DeviceLastNetworkLogon)
|
||||
{
|
||||
taskStatus.UpdateStatus(15, "Refreshing device last network logon dates from Active Directory");
|
||||
status.UpdateStatus(15, "Refreshing device last network logon dates from Active Directory");
|
||||
try
|
||||
{
|
||||
Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDates(database, ScheduledTaskMockStatus.Create("UpdateLastNetworkLogonDates"));
|
||||
@@ -59,119 +149,9 @@ namespace Disco.Services.Jobs.Exporting
|
||||
catch (Exception) { } // Ignore Errors
|
||||
}
|
||||
|
||||
taskStatus.UpdateStatus(25, "Extracting records from the database");
|
||||
status.UpdateStatus(25, "Extracting records from the database");
|
||||
|
||||
var records = BuildRecords(jobQuery).ToList();
|
||||
|
||||
records.ForEach(r =>
|
||||
{
|
||||
if (options.JobStatus)
|
||||
{
|
||||
r.JobStatus = JobExtensions.CalculateStatusId(
|
||||
r.Job.ClosedDate,
|
||||
r.Job.JobTypeId,
|
||||
r.JobMetaWarranty?.ExternalLoggedDate,
|
||||
r.JobMetaWarranty?.ExternalCompletedDate,
|
||||
r.JobMetaNonWarranty?.RepairerLoggedDate,
|
||||
r.JobMetaNonWarranty?.RepairerCompletedDate,
|
||||
r.JobMetaNonWarranty?.AccountingChargeRequiredDate,
|
||||
r.JobMetaNonWarranty?.AccountingChargeAddedDate,
|
||||
r.JobMetaNonWarranty?.AccountingChargePaidDate,
|
||||
r.JobMetaNonWarranty?.IsInsuranceClaim,
|
||||
r.JobMetaInsurance?.ClaimFormSentDate,
|
||||
r.Job.WaitingForUserAction,
|
||||
r.Job.DeviceReadyForReturn,
|
||||
r.Job.DeviceReturnedDate);
|
||||
}
|
||||
|
||||
if (options.UserDetailCustom && r.User != null)
|
||||
{
|
||||
var detailsService = new DetailsProviderService(database);
|
||||
r.UserCustomDetails = detailsService.GetDetails(r.User);
|
||||
}
|
||||
});
|
||||
|
||||
taskStatus.UpdateStatus(70, "Building metadata");
|
||||
var metadata = options.BuildMetadata(records);
|
||||
|
||||
if (metadata.Count == 0)
|
||||
throw new ArgumentException("At least one export field must be specified", "Options");
|
||||
|
||||
taskStatus.UpdateStatus(80, $"Formatting {records.Count} records for export");
|
||||
|
||||
return ExportHelpers.WriteExport(options, taskStatus, metadata, records);
|
||||
}
|
||||
|
||||
public static ExportResult GenerateExport(DiscoDataContext database, JobExportOptions options, IScheduledTaskStatus taskStatus)
|
||||
{
|
||||
Func<IQueryable<Job>, IQueryable<Job>> filter = q =>
|
||||
{
|
||||
var r = q.Where(j => j.OpenedDate >= options.FilterStartDate);
|
||||
if (options.FilterEndDate.HasValue)
|
||||
r = r.Where(j => j.OpenedDate <= options.FilterEndDate);
|
||||
|
||||
if (options.FilterJobTypeId != null)
|
||||
r = r.Where(j => j.JobTypeId == options.FilterJobTypeId);
|
||||
|
||||
if (options.FilterJobSubTypeIds?.Any() ?? false)
|
||||
r = r.Where(j => j.JobSubTypes.Any(st => options.FilterJobSubTypeIds.Contains(st.Id)));
|
||||
|
||||
if (options.FilterJobQueueId.HasValue)
|
||||
r = r.Where(j => j.JobQueues.Any(jq => !jq.RemovedDate.HasValue && jq.JobQueueId == options.FilterJobQueueId));
|
||||
|
||||
if (options.FilterJobStatusId != null)
|
||||
{
|
||||
if (options.FilterJobStatusId != Job.JobStatusIds.Closed)
|
||||
r = r.Where(j => j.ClosedDate == null);
|
||||
|
||||
switch (options.FilterJobStatusId)
|
||||
{
|
||||
case Job.JobStatusIds.Open:
|
||||
// already filtered
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingAccountingPayment:
|
||||
r = r.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.AccountingChargeAddedDate != null && j.JobMetaNonWarranty.AccountingChargePaidDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingAccountingCharge:
|
||||
r = r.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.AccountingChargeRequiredDate == null && (j.JobMetaNonWarranty.AccountingChargePaidDate != null || j.JobMetaNonWarranty.AccountingChargeAddedDate != null));
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingDeviceReturn:
|
||||
r = r.Where(j => j.DeviceReadyForReturn != null && j.DeviceReturnedDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingInsuranceProcessing:
|
||||
r = r.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.IsInsuranceClaim && j.JobMetaInsurance.ClaimFormSentDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingRepairs:
|
||||
r = r.Where(j => j.JobTypeId == JobType.JobTypeIds.HNWar && j.JobMetaNonWarranty.RepairerLoggedDate != null && j.JobMetaNonWarranty.RepairerCompletedDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingUserAction:
|
||||
r = r.Where(j => j.WaitingForUserAction != null);
|
||||
break;
|
||||
case Job.JobStatusIds.AwaitingWarrantyRepair:
|
||||
r = r.Where(j => j.JobTypeId == JobType.JobTypeIds.HWar && j.JobMetaWarranty.ExternalLoggedDate != null && j.JobMetaWarranty.ExternalCompletedDate == null);
|
||||
break;
|
||||
case Job.JobStatusIds.Closed:
|
||||
r = r.Where(j => j.ClosedDate != null);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown Job Status Id: {options.FilterJobStatusId}", nameof(options.FilterJobStatusId));
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
return GenerateExport(database, filter, options, taskStatus);
|
||||
}
|
||||
|
||||
public static ExportResult GenerateExport(DiscoDataContext database, JobExportOptions options)
|
||||
{
|
||||
return GenerateExport(database, options, ScheduledTaskMockStatus.Create("Job Export"));
|
||||
}
|
||||
|
||||
private static IEnumerable<JobExportRecord> BuildRecords(IQueryable<Job> jobs)
|
||||
{
|
||||
return jobs.Select(j => new JobExportRecord()
|
||||
var records = query.Select(j => new JobExportRecord()
|
||||
{
|
||||
Job = j,
|
||||
JobTypeDescription = j.JobType.Description,
|
||||
@@ -214,13 +194,43 @@ namespace Disco.Services.Jobs.Exporting
|
||||
DeviceProfileId = j.Device.DeviceProfileId,
|
||||
DeviceProfileName = j.Device.DeviceProfile.Name,
|
||||
DeviceProfileShortName = j.Device.DeviceProfile.ShortName,
|
||||
}).ToList();
|
||||
|
||||
records.ForEach(r =>
|
||||
{
|
||||
if (Options.JobStatus)
|
||||
{
|
||||
r.JobStatus = JobExtensions.CalculateStatusId(
|
||||
r.Job.ClosedDate,
|
||||
r.Job.JobTypeId,
|
||||
r.JobMetaWarranty?.ExternalLoggedDate,
|
||||
r.JobMetaWarranty?.ExternalCompletedDate,
|
||||
r.JobMetaNonWarranty?.RepairerLoggedDate,
|
||||
r.JobMetaNonWarranty?.RepairerCompletedDate,
|
||||
r.JobMetaNonWarranty?.AccountingChargeRequiredDate,
|
||||
r.JobMetaNonWarranty?.AccountingChargeAddedDate,
|
||||
r.JobMetaNonWarranty?.AccountingChargePaidDate,
|
||||
r.JobMetaNonWarranty?.IsInsuranceClaim,
|
||||
r.JobMetaInsurance?.ClaimFormSentDate,
|
||||
r.Job.WaitingForUserAction,
|
||||
r.Job.DeviceReadyForReturn,
|
||||
r.Job.DeviceReturnedDate);
|
||||
}
|
||||
|
||||
if (Options.UserDetailCustom && r.User != null)
|
||||
{
|
||||
var detailsService = new DetailsProviderService(database);
|
||||
r.UserCustomDetails = detailsService.GetDetails(r.User);
|
||||
}
|
||||
});
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
private static List<Metadata> BuildMetadata(this JobExportOptions options, List<JobExportRecord> records)
|
||||
public List<Metadata> BuildMetadata(DiscoDataContext database, List<JobExportRecord> records, IScheduledTaskStatus status)
|
||||
{
|
||||
IEnumerable<string> userDetailCustomKeys = null;
|
||||
if (options.UserDetailCustom)
|
||||
if (Options.UserDetailCustom)
|
||||
userDetailCustomKeys = records.Where(r => r.UserCustomDetails != null).SelectMany(r => r.UserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
var allAccessors = BuildRecordAccessors(userDetailCustomKeys);
|
||||
@@ -232,7 +242,7 @@ namespace Disco.Services.Jobs.Exporting
|
||||
property = p,
|
||||
details = (DisplayAttribute)p.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault()
|
||||
})
|
||||
.Where(p => p.details != null && (bool)p.property.GetValue(options))
|
||||
.Where(p => p.details != null && (bool)p.property.GetValue(Options))
|
||||
.SelectMany(p =>
|
||||
{
|
||||
var fieldMetadata = allAccessors[p.property.Name];
|
||||
@@ -397,6 +407,5 @@ namespace Disco.Services.Jobs.Exporting
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Models.Services.Logging;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Logging.Models;
|
||||
using Disco.Services.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -10,12 +14,56 @@ namespace Disco.Services.Logging
|
||||
{
|
||||
using Metadata = ExportFieldMetadata<LogLiveEvent>;
|
||||
|
||||
public static class LogExport
|
||||
public class LogExportContext : IExportContext<LogExportOptions, LogLiveEvent>
|
||||
{
|
||||
public static ExportResult GenerateExport(ExportFormat format, List<LogLiveEvent> records)
|
||||
{
|
||||
var options = new LogExportOptions(format);
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool TimestampSuffix { get; set; }
|
||||
public LogExportOptions Options { get; set; }
|
||||
|
||||
public string SuggestedFilenamePrefix { get; } = "DiscoIctLogs";
|
||||
public string ExcelWorksheetName { get; } = "Disco ICT Logs";
|
||||
public string ExcelTableName { get; } = "DiscoIctLogs";
|
||||
|
||||
[JsonConstructor]
|
||||
private LogExportContext()
|
||||
{
|
||||
}
|
||||
|
||||
public LogExportContext(string name, string description, bool timestampSuffix, LogExportOptions options)
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Name = name;
|
||||
Description = description;
|
||||
TimestampSuffix = timestampSuffix;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public LogExportContext(LogExportOptions options)
|
||||
: this("Log Export", null, true, options)
|
||||
{
|
||||
}
|
||||
|
||||
public ExportResult Export(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
=> Exporter.Export(database, this, status);
|
||||
|
||||
public List<LogLiveEvent> BuildRecords(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
{
|
||||
var logRetriever = new ReadLogContext()
|
||||
{
|
||||
Start = Options.StartDate,
|
||||
End = Options.EndDate,
|
||||
Module = Options.ModuleId,
|
||||
EventTypes = Options.EventTypeIds,
|
||||
Take = Options.Take,
|
||||
};
|
||||
|
||||
return logRetriever.Query(database);
|
||||
}
|
||||
|
||||
public List<Metadata> BuildMetadata(DiscoDataContext database, List<LogLiveEvent> records, IScheduledTaskStatus status)
|
||||
{
|
||||
const string DateFormat = "yyyy-MM-dd";
|
||||
const string DateTimeFormat = DateFormat + " HH:mm:ss";
|
||||
Func<object, string> csvStringEncoded = (o) => o == null ? null : $"\"{((string)o).Replace("\"", "\"\"")}\"";
|
||||
@@ -48,20 +96,7 @@ namespace Disco.Services.Logging
|
||||
}
|
||||
}
|
||||
|
||||
return ExportHelpers.WriteExport(options, ScheduledTaskMockStatus.Create("Export Disco ICT Logs"), metadata, records);
|
||||
}
|
||||
}
|
||||
|
||||
public class LogExportOptions : IExportOptions
|
||||
{
|
||||
public ExportFormat Format { get; set; }
|
||||
public string FilenamePrefix { get; } = "DiscoIctLogs";
|
||||
public string ExcelWorksheetName { get; set; } = "Disco ICT Logs";
|
||||
public string ExcelTableName { get; set; } = "DiscoIctLogs";
|
||||
|
||||
public LogExportOptions(ExportFormat format)
|
||||
{
|
||||
Format = format;
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
-36
@@ -2,8 +2,11 @@
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Models.Services.Users.UserFlags;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Plugins.Features.DetailsProvider;
|
||||
using Disco.Services.Tasks;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
@@ -14,48 +17,56 @@ namespace Disco.Services.Users.UserFlags
|
||||
{
|
||||
using Metadata = ExportFieldMetadata<UserFlagExportRecord>;
|
||||
|
||||
public class UserFlagExport
|
||||
public class UserFlagExportContext : IExportContext<UserFlagExportOptions, UserFlagExportRecord>
|
||||
{
|
||||
private readonly DiscoDataContext database;
|
||||
private readonly UserFlagExportOptions options;
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool TimestampSuffix { get; set; }
|
||||
public UserFlagExportOptions Options { get; set; }
|
||||
|
||||
public UserFlagExport(DiscoDataContext database, UserFlagExportOptions options)
|
||||
public string SuggestedFilenamePrefix { get; } = "UserFlagExport";
|
||||
public string ExcelWorksheetName { get; } = "UserFlagExport";
|
||||
public string ExcelTableName { get; } = "UserFlags";
|
||||
|
||||
[JsonConstructor]
|
||||
private UserFlagExportContext()
|
||||
{
|
||||
this.database = database;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public ExportResult Generate(IScheduledTaskStatus status)
|
||||
public UserFlagExportContext(string name, string description, bool timestampSuffix, UserFlagExportOptions options)
|
||||
{
|
||||
var records = BuildRecords(status);
|
||||
|
||||
var metadata = BuildMetadata(records, status);
|
||||
|
||||
if (metadata.Count == 0)
|
||||
throw new ArgumentException("At least one export field must be specified", nameof(options));
|
||||
|
||||
status.UpdateStatus(90, $"Formatting {records.Count} records for export");
|
||||
return ExportHelpers.WriteExport(options, status, metadata, records);
|
||||
Id = Guid.NewGuid();
|
||||
Name = name;
|
||||
Description = description;
|
||||
TimestampSuffix = timestampSuffix;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
private List<UserFlagExportRecord> BuildRecords(IScheduledTaskStatus status)
|
||||
public UserFlagExportContext(UserFlagExportOptions options)
|
||||
: this("User Flag Export", null, true, options)
|
||||
{
|
||||
}
|
||||
|
||||
public ExportResult Export(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
=> Exporter.Export(database, this, status);
|
||||
|
||||
public List<UserFlagExportRecord> BuildRecords(DiscoDataContext database, IScheduledTaskStatus status)
|
||||
{
|
||||
var query = database.UserFlagAssignments
|
||||
.Include(a => a.User.UserDetails)
|
||||
.Include(a => a.UserFlag)
|
||||
.Where(a => options.UserFlagIds.Contains(a.UserFlagId));
|
||||
.Where(a => Options.UserFlagIds.Contains(a.UserFlagId));
|
||||
|
||||
if (options.CurrentOnly)
|
||||
{
|
||||
if (Options.CurrentOnly)
|
||||
query = query.Where(a => !a.RemovedDate.HasValue);
|
||||
}
|
||||
|
||||
// Update Users
|
||||
if (options.UserDisplayName ||
|
||||
options.UserSurname ||
|
||||
options.UserGivenName ||
|
||||
options.UserPhoneNumber ||
|
||||
options.UserEmailAddress)
|
||||
if (Options.UserDisplayName ||
|
||||
Options.UserSurname ||
|
||||
Options.UserGivenName ||
|
||||
Options.UserPhoneNumber ||
|
||||
Options.UserEmailAddress)
|
||||
{
|
||||
status.UpdateStatus(5, "Refreshing user details from Active Directory");
|
||||
var userIds = query.Select(d => d.UserId).Distinct().ToList();
|
||||
@@ -72,11 +83,11 @@ namespace Disco.Services.Users.UserFlags
|
||||
status.UpdateStatus(15, "Extracting records from the database");
|
||||
|
||||
var records = query.Select(a => new UserFlagExportRecord()
|
||||
{
|
||||
Assignment = a
|
||||
}).ToList();
|
||||
{
|
||||
Assignment = a
|
||||
}).ToList();
|
||||
|
||||
if (options.UserDetailCustom)
|
||||
if (Options.UserDetailCustom)
|
||||
{
|
||||
status.UpdateStatus(50, "Extracting custom user detail records");
|
||||
|
||||
@@ -93,12 +104,12 @@ namespace Disco.Services.Users.UserFlags
|
||||
return records;
|
||||
}
|
||||
|
||||
private List<Metadata> BuildMetadata(List<UserFlagExportRecord> records, IScheduledTaskStatus status)
|
||||
public List<Metadata> BuildMetadata(DiscoDataContext database, List<UserFlagExportRecord> records, IScheduledTaskStatus status)
|
||||
{
|
||||
status.UpdateStatus(80, "Building metadata");
|
||||
|
||||
IEnumerable<string> userDetailCustomKeys = null;
|
||||
if (options.UserDetailCustom)
|
||||
if (Options.UserDetailCustom)
|
||||
userDetailCustomKeys = records.Where(r => r.UserCustomDetails != null).SelectMany(r => r.UserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
var accessors = BuildAccessors(userDetailCustomKeys);
|
||||
@@ -110,9 +121,9 @@ namespace Disco.Services.Users.UserFlags
|
||||
property = p,
|
||||
details = (DisplayAttribute)p.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault()
|
||||
})
|
||||
.Where(p => p.details != null && p.property.Name != nameof(options.CurrentOnly) && (bool)p.property.GetValue(options))
|
||||
.SelectMany(p =>
|
||||
{
|
||||
.Where(p => p.details != null && p.property.Name != nameof(Options.CurrentOnly) && (bool)p.property.GetValue(Options))
|
||||
.SelectMany(p =>
|
||||
{
|
||||
var fieldMetadata = accessors[p.property.Name];
|
||||
fieldMetadata.ForEach(f =>
|
||||
{
|
||||
@@ -171,6 +182,5 @@ namespace Disco.Services.Users.UserFlags
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Services.Users.UserFlags;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Disco.Services.Users.UserFlags
|
||||
{
|
||||
public class UserFlagExportTask : ScheduledTask
|
||||
{
|
||||
private const string JobDataMapContext = "Context";
|
||||
|
||||
public override string TaskName { get; } = "Export User Flags";
|
||||
public override bool SingleInstanceTask { get { return false; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
|
||||
public static ExportTaskContext<UserFlagExportOptions> ScheduleNow(UserFlagExportOptions options)
|
||||
{
|
||||
// Build Context
|
||||
var context = new ExportTaskContext<UserFlagExportOptions>(options);
|
||||
|
||||
// Build Data Map
|
||||
var task = new UserFlagExportTask();
|
||||
JobDataMap taskData = new JobDataMap() { { JobDataMapContext, context } };
|
||||
|
||||
// Schedule Task
|
||||
context.TaskStatus = task.ScheduleTask(taskData);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
var context = (ExportTaskContext<UserFlagExportOptions>)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext];
|
||||
|
||||
Status.UpdateStatus(10, "Exporting User Flag Records", "Starting...");
|
||||
|
||||
using (DiscoDataContext Database = new DiscoDataContext())
|
||||
{
|
||||
var export = new UserFlagExport(Database, context.Options);
|
||||
|
||||
context.Result = export.Generate(Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user