From 3aeb9374a9200d8e868ec49a8d3b4323db47ab94 Mon Sep 17 00:00:00 2001 From: Gary Sharp Date: Thu, 17 Jul 2025 13:09:10 +1000 Subject: [PATCH] feature: job export supports individual user details --- .../Services/Jobs/JobExportOptions.cs | 198 ++++---- Disco.Models/UI/Job/JobExportModel.cs | 3 + Disco.Services/Jobs/JobExport.cs | 38 +- Disco.Web/Controllers/JobController.cs | 4 + Disco.Web/Models/Job/ExportModel.cs | 2 + Disco.Web/Views/Job/Export.cshtml | 71 +-- Disco.Web/Views/Job/Export.generated.cs | 442 +++--------------- 7 files changed, 198 insertions(+), 560 deletions(-) diff --git a/Disco.Models/Services/Jobs/JobExportOptions.cs b/Disco.Models/Services/Jobs/JobExportOptions.cs index 1beb7ad8..73085a92 100644 --- a/Disco.Models/Services/Jobs/JobExportOptions.cs +++ b/Disco.Models/Services/Jobs/JobExportOptions.cs @@ -21,227 +21,227 @@ namespace Disco.Models.Services.Jobs public int? FilterJobQueueId { get; set; } // Job - [Display(ShortName = "Job", Name = "Identifier", Description = "The identifier of the job")] + [Display(GroupName = "Job", Name = "Identifier", Description = "The identifier of the job")] public bool JobId { get; set; } - [Display(ShortName = "Job", Name = "Status", Description = "The status of the job")] + [Display(GroupName = "Job", Name = "Status", Description = "The status of the job")] public bool JobStatus { get; set; } - [Display(ShortName = "Job", Name = "Type", Description = "The type of the job")] + [Display(GroupName = "Job", Name = "Type", Description = "The type of the job")] public bool JobType { get; set; } - [Display(ShortName = "Job", Name = "Sub Types", Description = "The sub types of the job")] + [Display(GroupName = "Job", Name = "Sub Types", Description = "The sub types of the job")] public bool JobSubTypes { get; set; } - [Display(ShortName = "Job", Name = "Opened Date", Description = "The date the job was opened")] + [Display(GroupName = "Job", Name = "Opened Date", Description = "The date the job was opened")] public bool JobOpenedDate { get; set; } - [Display(ShortName = "Job", Name = "Opened User", Description = "The user who opened the job")] + [Display(GroupName = "Job", Name = "Opened User", Description = "The user who opened the job")] public bool JobOpenedUser { get; set; } - [Display(ShortName = "Job", Name = "Expected Closed Date", Description = "The expected closed date of the job")] + [Display(GroupName = "Job", Name = "Expected Closed Date", Description = "The expected closed date of the job")] public bool JobExpectedClosedDate { get; set; } - [Display(ShortName = "Job", Name = "Closed Date", Description = "The date the job was closed")] + [Display(GroupName = "Job", Name = "Closed Date", Description = "The date the job was closed")] public bool JobClosedDate { get; set; } - [Display(ShortName = "Job", Name = "Closed User", Description = "The user who closed the job")] + [Display(GroupName = "Job", Name = "Closed User", Description = "The user who closed the job")] public bool JobClosedUser { get; set; } // Job Details - [Display(ShortName = "Job Details", Name = "Held Date", Description = "The date the device was held")] + [Display(GroupName = "Job Details", Name = "Held Date", Description = "The date the device was held")] public bool JobDeviceHeldDate { get; set; } - [Display(ShortName = "Job Details", Name = "Held User", Description = "The user who held the device")] + [Display(GroupName = "Job Details", Name = "Held User", Description = "The user who held the device")] public bool JobDeviceHeldUser { get; set; } - [Display(ShortName = "Job Details", Name = "Held Location", Description = "The location the device was held")] + [Display(GroupName = "Job Details", Name = "Held Location", Description = "The location the device was held")] public bool JobDeviceHeldLocation { get; set; } - [Display(ShortName = "Job Details", Name = "Ready For Return Date", Description = "The date the device was ready for return")] + [Display(GroupName = "Job Details", Name = "Ready For Return Date", Description = "The date the device was ready for return")] public bool JobDeviceReadyForReturnDate { get; set; } - [Display(ShortName = "Job Details", Name = "Ready For Return User", Description = "The user who made the device ready for return")] + [Display(GroupName = "Job Details", Name = "Ready For Return User", Description = "The user who made the device ready for return")] public bool JobDeviceReadyForReturnUser { get; set; } - [Display(ShortName = "Job Details", Name = "Returned Date", Description = "The date the device was returned")] + [Display(GroupName = "Job Details", Name = "Returned Date", Description = "The date the device was returned")] public bool JobDeviceReturnedDate { get; set; } - [Display(ShortName = "Job Details", Name = "Returned User", Description = "The user who returned the device")] + [Display(GroupName = "Job Details", Name = "Returned User", Description = "The user who returned the device")] public bool JobDeviceReturnedUser { get; set; } - [Display(ShortName = "Job Details", Name = "Waiting For User Action Date", Description = "The date the job was waiting for user action")] + [Display(GroupName = "Job Details", Name = "Waiting For User Action Date", Description = "The date the job was waiting for user action")] public bool JobWaitingForUserActionDate { get; set; } // Job Log - [Display(ShortName = "Job Log", Name = "Count", Description = "The number of log entries for the job")] + [Display(GroupName = "Job Log", Name = "Count", Description = "The number of log entries for the job")] public bool LogCount { get; set; } - [Display(ShortName = "Job Log", Name = "First Date", Description = "The date of the first log entry for the job")] + [Display(GroupName = "Job Log", Name = "First Date", Description = "The date of the first log entry for the job")] public bool LogFirstDate { get; set; } - [Display(ShortName = "Job Log", Name = "First User", Description = "The user who made the first log entry for the job")] + [Display(GroupName = "Job Log", Name = "First User", Description = "The user who made the first log entry for the job")] public bool LogFirstUser { get; set; } - [Display(ShortName = "Job Log", Name = "First Content", Description = "The content of the first log entry for the job")] + [Display(GroupName = "Job Log", Name = "First Content", Description = "The content of the first log entry for the job")] public bool LogFirstContent { get; set; } - [Display(ShortName = "Job Log", Name = "Last Date", Description = "The date of the last log entry for the job")] + [Display(GroupName = "Job Log", Name = "Last Date", Description = "The date of the last log entry for the job")] public bool LogLastDate { get; set; } - [Display(ShortName = "Job Log", Name = "Last User", Description = "The user who made the last log entry for the job")] + [Display(GroupName = "Job Log", Name = "Last User", Description = "The user who made the last log entry for the job")] public bool LogLastUser { get; set; } - [Display(ShortName = "Job Log", Name = "Last Content", Description = "The content of the last log entry for the job")] + [Display(GroupName = "Job Log", Name = "Last Content", Description = "The content of the last log entry for the job")] public bool LogLastContent { get; set; } // Job Attachments - [Display(ShortName = "Job Attachments", Name = "Count", Description = "The number of attachments for the job")] + [Display(GroupName = "Job Attachments", Name = "Count", Description = "The number of attachments for the job")] public bool AttachmentsCount { get; set; } // Job Queues - [Display(ShortName = "Job Queues", Name = "Count", Description = "The number of times the job has been associated with a queue")] + [Display(GroupName = "Job Queues", Name = "Count", Description = "The number of times the job has been associated with a queue")] public bool JobQueueCount { get; set; } - [Display(ShortName = "Job Queues", Name = "Active Count", Description = "The number of active queues the job is associated with")] + [Display(GroupName = "Job Queues", Name = "Active Count", Description = "The number of active queues the job is associated with")] public bool JobQueueActiveCount { get; set; } - [Display(ShortName = "Job Queues", Name = "Active Latest", Description = "The latest queue the job is associated with")] + [Display(GroupName = "Job Queues", Name = "Active Latest", Description = "The latest queue the job is associated with")] public bool JobQueueActiveLatest { get; set; } - [Display(ShortName = "Job Queues", Name = "Active Latest Date", Description = "The date the latest queue was added")] + [Display(GroupName = "Job Queues", Name = "Active Latest Date", Description = "The date the latest queue was added")] public bool JobQueueActiveLatestAddedDate { get; set; } - [Display(ShortName = "Job Queues", Name = "Active Latest User", Description = "The user who added the latest queue")] + [Display(GroupName = "Job Queues", Name = "Active Latest User", Description = "The user who added the latest queue")] public bool JobQueueActiveLatestAddedUser { get; set; } // Job Type - Warranty - [Display(ShortName = "Job Warranty", Name = "External Name", Description = "The name of the external warranty provider")] + [Display(GroupName = "Job Warranty", Name = "External Name", Description = "The name of the external warranty provider")] public bool JobWarrantyExternalName { get; set; } - [Display(ShortName = "Job Warranty", Name = "External Logged Date", Description = "The date the warranty was logged with the external provider")] + [Display(GroupName = "Job Warranty", Name = "External Logged Date", Description = "The date the warranty was logged with the external provider")] public bool JobWarrantyExternalLoggedDate { get; set; } - [Display(ShortName = "Job Warranty", Name = "External Reference", Description = "The reference of the warranty with the external provider")] + [Display(GroupName = "Job Warranty", Name = "External Reference", Description = "The reference of the warranty with the external provider")] public bool JobWarrantyExternalReference { get; set; } - [Display(ShortName = "Job Warranty", Name = "External Completed Date", Description = "The date the warranty was completed with the external provider")] + [Display(GroupName = "Job Warranty", Name = "External Completed Date", Description = "The date the warranty was completed with the external provider")] public bool JobWarrantyExternalCompletedDate { get; set; } // Job Type - NonWarranty - [Display(ShortName = "Job Non Warranty", Name = "Accounting Charge Required Date", Description = "The date the accounting charge was required")] + [Display(GroupName = "Job Non Warranty", Name = "Accounting Charge Required Date", Description = "The date the accounting charge was required")] public bool JobNonWarrantyAccountingChargeRequiredDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Accounting Charge Added Date", Description = "The date the accounting charge was added")] + [Display(GroupName = "Job Non Warranty", Name = "Accounting Charge Added Date", Description = "The date the accounting charge was added")] public bool JobNonWarrantyAccountingChargeAddedDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Accounting Charge Paid Date", Description = "The date the accounting charge was paid")] + [Display(GroupName = "Job Non Warranty", Name = "Accounting Charge Paid Date", Description = "The date the accounting charge was paid")] public bool JobNonWarrantyAccountingChargePaidDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Purchase Order Raised Date", Description = "The date the purchase order was raised")] + [Display(GroupName = "Job Non Warranty", Name = "Purchase Order Raised Date", Description = "The date the purchase order was raised")] public bool JobNonWarrantyPurchaseOrderRaisedDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Purchase Order Reference", Description = "The reference of the purchase order")] + [Display(GroupName = "Job Non Warranty", Name = "Purchase Order Reference", Description = "The reference of the purchase order")] public bool JobNonWarrantyPurchaseOrderReference { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Purchase Order Sent Date", Description = "The date the purchase order was sent")] + [Display(GroupName = "Job Non Warranty", Name = "Purchase Order Sent Date", Description = "The date the purchase order was sent")] public bool JobNonWarrantyPurchaseOrderSentDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Invoice Received Date", Description = "The date the invoice was received")] + [Display(GroupName = "Job Non Warranty", Name = "Invoice Received Date", Description = "The date the invoice was received")] public bool JobNonWarrantyInvoiceReceivedDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Repairer Name", Description = "The name of the repairer")] + [Display(GroupName = "Job Non Warranty", Name = "Repairer Name", Description = "The name of the repairer")] public bool JobNonWarrantyRepairerName { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Repairer Logged Date", Description = "The date the job was logged with the repairer")] + [Display(GroupName = "Job Non Warranty", Name = "Repairer Logged Date", Description = "The date the job was logged with the repairer")] public bool JobNonWarrantyRepairerLoggedDate { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Repairer Reference", Description = "The repairer reference for the job")] + [Display(GroupName = "Job Non Warranty", Name = "Repairer Reference", Description = "The repairer reference for the job")] public bool JobNonWarrantyRepairerReference { get; set; } - [Display(ShortName = "Job Non Warranty", Name = "Repairer Completed Date", Description = "The date the repairer completed the job")] + [Display(GroupName = "Job Non Warranty", Name = "Repairer Completed Date", Description = "The date the repairer completed the job")] public bool JobNonWarrantyRepairerCompletedDate { get; set; } // Job Type - Insurance - [Display(ShortName = "Job Insurance", Name = "Loss Or Damage Date", Description = "The date of the loss or damage")] + [Display(GroupName = "Job Insurance", Name = "Loss Or Damage Date", Description = "The date of the loss or damage")] public bool JobMetaInsuranceLossOrDamageDate { get; set; } - [Display(ShortName = "Job Insurance", Name = "Event Location", Description = "The location of the event")] + [Display(GroupName = "Job Insurance", Name = "Event Location", Description = "The location of the event")] public bool JobMetaInsuranceEventLocation { get; set; } - [Display(ShortName = "Job Insurance", Name = "Description", Description = "The description of the event")] + [Display(GroupName = "Job Insurance", Name = "Description", Description = "The description of the event")] public bool JobMetaInsuranceDescription { get; set; } - [Display(ShortName = "Job Insurance", Name = "Third Party Caused Name", Description = "The name of the third party which caused the event")] + [Display(GroupName = "Job Insurance", Name = "Third Party Caused Name", Description = "The name of the third party which caused the event")] public bool JobMetaInsuranceThirdPartyCausedName { get; set; } - [Display(ShortName = "Job Insurance", Name = "Third Party Caused Why", Description = "The reason the third party caused the event")] + [Display(GroupName = "Job Insurance", Name = "Third Party Caused Why", Description = "The reason the third party caused the event")] public bool JobMetaInsuranceThirdPartyCausedWhy { get; set; } - [Display(ShortName = "Job Insurance", Name = "Witnesses Names Addresses", Description = "The names and addresses of the witnesses")] + [Display(GroupName = "Job Insurance", Name = "Witnesses Names Addresses", Description = "The names and addresses of the witnesses")] public bool JobMetaInsuranceWitnessesNamesAddresses { get; set; } - [Display(ShortName = "Job Insurance", Name = "Burglary Theft Method Of Entry", Description = "The method of entry for a burglary or theft")] + [Display(GroupName = "Job Insurance", Name = "Burglary Theft Method Of Entry", Description = "The method of entry for a burglary or theft")] public bool JobMetaInsuranceBurglaryTheftMethodOfEntry { get; set; } - [Display(ShortName = "Job Insurance", Name = "Property Last Seen Date", Description = "The date the property was last seen")] + [Display(GroupName = "Job Insurance", Name = "Property Last Seen Date", Description = "The date the property was last seen")] public bool JobMetaInsurancePropertyLastSeenDate { get; set; } - [Display(ShortName = "Job Insurance", Name = "Police Station Notified", Description = "The police station which was notified")] + [Display(GroupName = "Job Insurance", Name = "Police Station Notified", Description = "The police station which was notified")] public bool JobMetaInsurancePoliceNotifiedStation { get; set; } - [Display(ShortName = "Job Insurance", Name = "Police Notified Date", Description = "The date the police were notified")] + [Display(GroupName = "Job Insurance", Name = "Police Notified Date", Description = "The date the police were notified")] public bool JobMetaInsurancePoliceNotifiedDate { get; set; } - [Display(ShortName = "Job Insurance", Name = "Police Crime Report Number", Description = "The crime report number provided by the police")] + [Display(GroupName = "Job Insurance", Name = "Police Crime Report Number", Description = "The crime report number provided by the police")] public bool JobMetaInsurancePoliceNotifiedCrimeReportNo { get; set; } - [Display(ShortName = "Job Insurance", Name = "Recover Reduce Action", Description = "The action taken to recover or reduce the loss")] + [Display(GroupName = "Job Insurance", Name = "Recover Reduce Action", Description = "The action taken to recover or reduce the loss")] public bool JobMetaInsuranceRecoverReduceAction { get; set; } - [Display(ShortName = "Job Insurance", Name = "Other Interested Parties", Description = "Other parties interested in the event")] + [Display(GroupName = "Job Insurance", Name = "Other Interested Parties", Description = "Other parties interested in the event")] public bool JobMetaInsuranceOtherInterestedParties { get; set; } - [Display(ShortName = "Job Insurance", Name = "Date Of Purchase", Description = "The date the item was purchased")] + [Display(GroupName = "Job Insurance", Name = "Date Of Purchase", Description = "The date the item was purchased")] public bool JobMetaInsuranceDateOfPurchase { get; set; } - [Display(ShortName = "Job Insurance", Name = "Claim Form Sent Date", Description = "The date the claim form was sent")] + [Display(GroupName = "Job Insurance", Name = "Claim Form Sent Date", Description = "The date the claim form was sent")] public bool JobMetaInsuranceClaimFormSentDate { get; set; } - [Display(ShortName = "Job Insurance", Name = "Insurer", Description = "The insurer associated with the claim")] + [Display(GroupName = "Job Insurance", Name = "Insurer", Description = "The insurer associated with the claim")] public bool JobMetaInsuranceInsurer { get; set; } - [Display(ShortName = "Job Insurance", Name = "Insurer Reference", Description = "The reference provided by the insurer")] + [Display(GroupName = "Job Insurance", Name = "Insurer Reference", Description = "The reference provided by the insurer")] public bool JobMetaInsuranceInsurerReference { get; set; } // Job Type = User Management - [Display(ShortName = "Job User Management", Name = "Flags", Description = "The user management flags associated with the job")] + [Display(GroupName = "Job User Management", Name = "Flags", Description = "The user management flags associated with the job")] public bool JobUserManagementFlags { get; set; } // User - [Display(ShortName = "User", Name = "Identifier", Description = "The identifier of the user associated with the job")] + [Display(GroupName = "User", Name = "Identifier", Description = "The identifier of the user associated with the job")] public bool UserId { get; set; } - [Display(ShortName = "User", Name = "Display Name", Description = "The display name of the user associated with the job")] + [Display(GroupName = "User", Name = "Display Name", Description = "The display name of the user associated with the job")] public bool UserDisplayName { get; set; } - [Display(ShortName = "User", Name = "Surname", Description = "The surname of the user associated with the job")] + [Display(GroupName = "User", Name = "Surname", Description = "The surname of the user associated with the job")] public bool UserSurname { get; set; } - [Display(ShortName = "User", Name = "Given Name", Description = "The given name of the user associated with the job")] + [Display(GroupName = "User", Name = "Given Name", Description = "The given name of the user associated with the job")] public bool UserGivenName { get; set; } - [Display(ShortName = "User", Name = "Phone Number", Description = "The phone number of the user associated with the job")] + [Display(GroupName = "User", Name = "Phone Number", Description = "The phone number of the user associated with the job")] public bool UserPhoneNumber { get; set; } - [Display(ShortName = "User", Name = "Email Address", Description = "The email address of the user associated with the job")] + [Display(GroupName = "User", Name = "Email Address", Description = "The email address of the user associated with the job")] public bool UserEmailAddress { get; set; } - [Display(ShortName = "User", Name = "Custom Details", Description = "The custom details provided by plugins for the user associated with the job")] - public bool UserDetailCustom { get; set; } + [Display(GroupName = "User", Name = "Custom Details", Description = "The custom details provided by plugins for the user associated with the job")] + public List UserDetailsCustom { get; set; } = new List(); // Device - [Display(ShortName = "Device", Name = "Serial Number", Description = "The device serial number")] + [Display(GroupName = "Device", Name = "Serial Number", Description = "The device serial number")] public bool DeviceSerialNumber { get; set; } - [Display(ShortName = "Device", Name = "Asset Number", Description = "The device asset number")] + [Display(GroupName = "Device", Name = "Asset Number", Description = "The device asset number")] public bool DeviceAssetNumber { get; set; } - [Display(ShortName = "Device", Name = "Location", Description = "The device location")] + [Display(GroupName = "Device", Name = "Location", Description = "The device location")] public bool DeviceLocation { get; set; } - [Display(ShortName = "Device", Name = "Computer Name", Description = "The device computer name")] + [Display(GroupName = "Device", Name = "Computer Name", Description = "The device computer name")] public bool DeviceComputerName { get; set; } - [Display(ShortName = "Device", Name = "Last Network Logon", Description = "The last recorded time the device access the network")] + [Display(GroupName = "Device", Name = "Last Network Logon", Description = "The last recorded time the device access the network")] public bool DeviceLastNetworkLogon { get; set; } - [Display(ShortName = "Device", Name = "Created Date", Description = "The date the device was created in Disco ICT")] + [Display(GroupName = "Device", Name = "Created Date", Description = "The date the device was created in Disco ICT")] public bool DeviceCreatedDate { get; set; } - [Display(ShortName = "Device", Name = "First Enrolled Date", Description = "The date the device was first enrolled in Disco ICT")] + [Display(GroupName = "Device", Name = "First Enrolled Date", Description = "The date the device was first enrolled in Disco ICT")] public bool DeviceFirstEnrolledDate { get; set; } - [Display(ShortName = "Device", Name = "Last Enrolled Date", Description = "The date the device was last enrolled in Disco ICT")] + [Display(GroupName = "Device", Name = "Last Enrolled Date", Description = "The date the device was last enrolled in Disco ICT")] public bool DeviceLastEnrolledDate { get; set; } - [Display(ShortName = "Device", Name = "Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")] + [Display(GroupName = "Device", Name = "Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")] public bool DeviceAllowUnauthenticatedEnrol { get; set; } - [Display(ShortName = "Device", Name = "Decommissioned Date", Description = "The date the device was decommissioned in Disco ICT")] + [Display(GroupName = "Device", Name = "Decommissioned Date", Description = "The date the device was decommissioned in Disco ICT")] public bool DeviceDecommissionedDate { get; set; } - [Display(ShortName = "Device", Name = "Decommissioned Reason", Description = "The reason the device was decommissioned")] + [Display(GroupName = "Device", Name = "Decommissioned Reason", Description = "The reason the device was decommissioned")] public bool DeviceDecommissionedReason { get; set; } // Model - [Display(ShortName = "Device Model", Name = "Identifier", Description = "The identifier of the device model associated with the job")] + [Display(GroupName = "Device Model", Name = "Identifier", Description = "The identifier of the device model associated with the job")] public bool DeviceModelId { get; set; } - [Display(ShortName = "Device Model", Name = "Description", Description = "The description of the device model associated with the job")] + [Display(GroupName = "Device Model", Name = "Description", Description = "The description of the device model associated with the job")] public bool DeviceModelDescription { get; set; } - [Display(ShortName = "Device Model", Name = "Manufacturer", Description = "The manufacturer of the device model associated with the job")] + [Display(GroupName = "Device Model", Name = "Manufacturer", Description = "The manufacturer of the device model associated with the job")] public bool DeviceModelManufacturer { get; set; } - [Display(ShortName = "Device Model", Name = "Model", Description = "The model of the device model associated with the job")] + [Display(GroupName = "Device Model", Name = "Model", Description = "The model of the device model associated with the job")] public bool DeviceModelModel { get; set; } - [Display(ShortName = "Device Model", Name = "Type", Description = "The type of device model associated with the job")] + [Display(GroupName = "Device Model", Name = "Type", Description = "The type of device model associated with the job")] public bool DeviceModelType { get; set; } // Batch - [Display(ShortName = "Device Batch", Name = "Identifier", Description = "The identifier of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Identifier", Description = "The identifier of the device batch associated with the job")] public bool DeviceBatchId { get; set; } - [Display(ShortName = "Device Batch", Name = "Name", Description = "The name of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Name", Description = "The name of the device batch associated with the job")] public bool DeviceBatchName { get; set; } - [Display(ShortName = "Device Batch", Name = "Purchase Date", Description = "The purchase date of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Purchase Date", Description = "The purchase date of the device batch associated with the job")] public bool DeviceBatchPurchaseDate { get; set; } - [Display(ShortName = "Device Batch", Name = "Supplier", Description = "The supplier of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Supplier", Description = "The supplier of the device batch associated with the job")] public bool DeviceBatchSupplier { get; set; } - [Display(ShortName = "Device Batch", Name = "Unit Cost", Description = "The unit cost of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Unit Cost", Description = "The unit cost of the device batch associated with the job")] public bool DeviceBatchUnitCost { get; set; } - [Display(ShortName = "Device Batch", Name = "Warranty Valid Until Date", Description = "The warranty valid until date of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Warranty Valid Until Date", Description = "The warranty valid until date of the device batch associated with the job")] public bool DeviceBatchWarrantyValidUntilDate { get; set; } - [Display(ShortName = "Device Batch", Name = "Insured Date", Description = "The insured date of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Insured Date", Description = "The insured date of the device batch associated with the job")] public bool DeviceBatchInsuredDate { get; set; } - [Display(ShortName = "Device Batch", Name = "Insurance Supplier", Description = "The insurance supplier of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Insurance Supplier", Description = "The insurance supplier of the device batch associated with the job")] public bool DeviceBatchInsuranceSupplier { get; set; } - [Display(ShortName = "Device Batch", Name = "Insured Until Date", Description = "The insured until date of the device batch associated with the job")] + [Display(GroupName = "Device Batch", Name = "Insured Until Date", Description = "The insured until date of the device batch associated with the job")] public bool DeviceBatchInsuredUntilDate { get; set; } // Profile - [Display(ShortName = "Device Profile", Name = "Identifier", Description = "The identifier of the device profile associated with the job")] + [Display(GroupName = "Device Profile", Name = "Identifier", Description = "The identifier of the device profile associated with the job")] public bool DeviceProfileId { get; set; } - [Display(ShortName = "Device Profile", Name = "Name", Description = "The name of the device profile associated with the job")] + [Display(GroupName = "Device Profile", Name = "Name", Description = "The name of the device profile associated with the job")] public bool DeviceProfileName { get; set; } - [Display(ShortName = "Device Profile", Name = "Short Name", Description = "The short name of the device profile associated with the job")] + [Display(GroupName = "Device Profile", Name = "Short Name", Description = "The short name of the device profile associated with the job")] public bool DeviceProfileShortName { get; set; } public static JobExportOptions DefaultOptions() diff --git a/Disco.Models/UI/Job/JobExportModel.cs b/Disco.Models/UI/Job/JobExportModel.cs index d395f119..3fb98ac6 100644 --- a/Disco.Models/UI/Job/JobExportModel.cs +++ b/Disco.Models/UI/Job/JobExportModel.cs @@ -1,6 +1,7 @@ using Disco.Models.Repository; using Disco.Models.Services.Exporting; using Disco.Models.Services.Jobs; +using Disco.Models.UI.Shared; using System; using System.Collections.Generic; @@ -16,5 +17,7 @@ namespace Disco.Models.UI.Job List JobQueues { get; set; } List> JobStatuses { get; set; } List JobTypes { get; set; } + + SharedExportFieldsModel Fields { get; set; } } } diff --git a/Disco.Services/Jobs/JobExport.cs b/Disco.Services/Jobs/JobExport.cs index b39061b5..ec6ba700 100644 --- a/Disco.Services/Jobs/JobExport.cs +++ b/Disco.Services/Jobs/JobExport.cs @@ -1,6 +1,7 @@ using Disco.Data.Repository; using Disco.Models.Exporting; using Disco.Models.Repository; +using Disco.Models.Services.Devices; using Disco.Models.Services.Exporting; using Disco.Models.Services.Jobs; using Disco.Services.Exporting; @@ -12,6 +13,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace Disco.Services.Jobs { @@ -205,17 +207,32 @@ namespace Disco.Services.Jobs r.Job.DeviceReadyForReturn, r.Job.DeviceReturnedDate); } - - if (Options.UserDetailCustom && r.User != null) - { - var detailsService = new DetailsProviderService(database); - r.UserCustomDetails = detailsService.GetDetails(r.User); - } }); + if (Options.UserDetailsCustom?.Any() ?? false) + AddUserCustomDetails(database, records, status); + return records; } + private static void AddUserCustomDetails(DiscoDataContext database, List records, IScheduledTaskStatus status) + { + if (!records.Any(r => r.User != null)) + return; + status.UpdateStatus(50, "Extracting custom user detail records"); + var detailsService = new DetailsProviderService(database); + var cache = new Dictionary>(StringComparer.Ordinal); + foreach (var record in records) + { + var userId = record.User?.UserId; + if (string.IsNullOrWhiteSpace(userId)) + continue; + if (!cache.TryGetValue(userId, out var details)) + details = detailsService.GetDetails(record.User); + record.UserCustomDetails = details; + } + } + public ExportMetadata BuildMetadata(DiscoDataContext database, List records, IScheduledTaskStatus status) { var metadata = new ExportMetadata(Options); @@ -312,13 +329,10 @@ namespace Disco.Services.Jobs metadata.Add(o => o.UserEmailAddress, r => r.User?.EmailAddress); // User Custom Details - if (Options.UserDetailCustom) + if (Options.UserDetailsCustom.Any()) { - var keys = records.Where(r => r.UserCustomDetails != null).SelectMany(r => r.UserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - foreach (var key in keys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase)) - { - metadata.Add(key, r => r.UserCustomDetails != null && r.UserCustomDetails.TryGetValue(key, out var value) ? value : null); - } + foreach (var key in Options.UserDetailsCustom.OrderBy(k => k, StringComparer.OrdinalIgnoreCase)) + metadata.Add($"User Detail {key.TrimEnd('*', '&')}", r => r.UserCustomDetails != null && r.UserCustomDetails.TryGetValue(key, out var value) ? value : null); } // Device diff --git a/Disco.Web/Controllers/JobController.cs b/Disco.Web/Controllers/JobController.cs index e341823c..580cdb05 100644 --- a/Disco.Web/Controllers/JobController.cs +++ b/Disco.Web/Controllers/JobController.cs @@ -18,6 +18,7 @@ using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Users; using Disco.Services.Web; +using Disco.Web.Models.Shared; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -1092,6 +1093,9 @@ namespace Disco.Web.Controllers JobStatuses = Job.JobStatusIds.StatusDescriptions.ToList(), }; + m.Fields = ExportFieldsModel.Create(m.Options, JobExportOptions.DefaultOptions()); + m.Fields.AddCustomUserDetails(o => o.UserDetailsCustom, m.Fields.FieldGroups.FindIndex(g => g.Name == "User") + 1); + if (Database.DiscoConfiguration.JobPreferences.LastExportDate.GetValueOrDefault() < DateTime.Today.AddDays(-1)) { m.Options.FilterStartDate = new DateTime(DateTime.Today.Year, 1, 1); diff --git a/Disco.Web/Models/Job/ExportModel.cs b/Disco.Web/Models/Job/ExportModel.cs index 7c55be2e..eebd56a3 100644 --- a/Disco.Web/Models/Job/ExportModel.cs +++ b/Disco.Web/Models/Job/ExportModel.cs @@ -2,6 +2,7 @@ using Disco.Models.Services.Exporting; using Disco.Models.Services.Jobs; using Disco.Models.UI.Job; +using Disco.Models.UI.Shared; using System; using System.Collections.Generic; @@ -18,5 +19,6 @@ namespace Disco.Web.Models.Job public List> JobStatuses { get; set; } public List JobTypes { get; set; } + public SharedExportFieldsModel Fields { get; set; } } } diff --git a/Disco.Web/Views/Job/Export.cshtml b/Disco.Web/Views/Job/Export.cshtml index cef06ae9..9ed5379f 100644 --- a/Disco.Web/Views/Job/Export.cshtml +++ b/Disco.Web/Views/Job/Export.cshtml @@ -103,54 +103,7 @@ -
-

Export Fields (Defaults)

- - @foreach (var optionGroup in optionGroups) - { - var optionFields = optionGroup.ToList(); - var itemsPerColumn = (int)Math.Ceiling((double)optionFields.Count / 2); - - - - - - } -
- @optionGroup.Key - @if (optionFields.Count > 2) - { - ALL | NONE - } - -
- - - - - -
-
    - @foreach (var optionItem in optionFields.Take(itemsPerColumn)) - { -
  • - -
  • - } -
-
-
    - @foreach (var optionItem in optionFields.Skip(itemsPerColumn)) - { -
  • - -
  • - } -
-
-
-
-
+ @Html.Partial(MVC.Shared.Views._ExportFields, Model.Fields.FieldGroups) \r\n"); +", \'UserDisplayName\'];\r\n var $form = $FilterStartDate.closest(\'for" + +"m\');\r\n\r\n function exportTypeChange() {\r\n $expo" + +"rtTypeTargetContainers.hide();\r\n $exportTypeTargetContainers." + +"find(\'select\').prop(\'disabled\', true);\r\n\r\n switch ($exportTyp" + +"e.val()) {\r\n case \'Batch\':\r\n $" + +"(\'#Devices_Export_Type_Target_Batch\').show().find(\'select\').prop(\'disabled\', fal" + +"se);\r\n break;\r\n case \'Profile\'" + +":\r\n $(\'#Devices_Export_Type_Target_Profile\').show().f" + +"ind(\'select\').prop(\'disabled\', false);\r\n break;\r\n " + +" case \'Model\':\r\n $(\'#Devices_Expor" + +"t_Type_Target_Model\').show().find(\'select\').prop(\'disabled\', false);\r\n " + +" break;\r\n }\r\n }\r\n " + +" $FilterJobTypeId\r\n .on(\'change\', function (e) {\r\n " + +" $(\'#Jobs_Export_SubTypes\').hide()\r\n ." + +"find(\'.Jobs_Export_SubType_Target\').hide()\r\n .find(\'i" + +"nput\').prop(\'disabled\', true);\r\n\r\n const type = $(e.curre" + +"ntTarget).val();\r\n if (type) {\r\n " + +" $(\'#Jobs_Export_SubTypes\').show()\r\n $(\'#Jobs_Expor" + +"t_SubTypes_\' + type).show()\r\n .find(\'input\').prop" + +"(\'disabled\', false);\r\n }\r\n }).trigger(" + +"\'change\');\r\n $(\'#Jobs_Export_SubTypes\').on(\'click\', \'a.selectAll," + +"a.selectNone\', function (e) {\r\n e.preventDefault();\r\n " + +" var $this = $(this);\r\n $this.closest(\'div\').find(" + +"\'input\').prop(\'checked\', $this.is(\'.selectAll\'));\r\n return fa" + +"lse;\r\n });\r\n\r\n $.validator.unobtrusive.parse($form" + +");\r\n $form.data(\"validator\").settings.submitHandler = function ()" + +" {\r\n var exportFieldCount = $(\'#Export_Fields\').find(\'input:c" + +"hecked\').length;\r\n\r\n if (exportFieldCount > 0) {\r\n\r\n " + +" const $exportingDialog = $(\'#Export_Exporting\').dialog({\r\n " + +" width: 400,\r\n height: 164,\r\n " + +" resizable: false,\r\n modal: tr" + +"ue,\r\n autoOpen: true\r\n });\r\n\r\n" + +" $form[0].submit();\r\n }\r\n " + +" else\r\n alert(\'Select at least one field to export." + +"\');\r\n };\r\n\r\n $(\'#Jobs_Export_Button\').click(functi" + +"on () {\r\n $form.submit();\r\n });\r\n " + +" $(\'#Jobs_Export_Save_Button\').click(function () {\r\n $form." + +"attr(\'action\', $form[0].dataset.saveaction);\r\n $form.submit()" + +";\r\n });\r\n });\r\n \r\n"); - #line 251 "..\..\Views\Job\Export.cshtml" + #line 184 "..\..\Views\Job\Export.cshtml" } @@ -958,7 +640,7 @@ WriteLiteral("