瀏覽代碼

Added ability to set Job and Job Scope from digital forms dock

Kenric Nugteren 1 年之前
父節點
當前提交
1f6fbcbd56
共有 1 個文件被更改,包括 271 次插入6 次删除
  1. 271 6
      prs.desktop/DockPanels/DigitalFormsDock.xaml.cs

+ 271 - 6
prs.desktop/DockPanels/DigitalFormsDock.xaml.cs

@@ -16,6 +16,8 @@ using InABox.Scripting;
 using InABox.Wpf.Reports;
 using InABox.WPF;
 using PRSDesktop.Configuration;
+using System.Diagnostics;
+using System.Threading.Tasks;
 
 namespace PRSDesktop
 {
@@ -50,6 +52,8 @@ namespace PRSDesktop
         [NullEditor]
         public DateTime Processed { get; set; }
 
+        [NullEditor]
+        public Guid ParentID { get; set; }
     }
     
     public class DigitalFormDockGrid : DynamicGrid<DigitalFormDockModel>
@@ -98,7 +102,8 @@ namespace PRSDesktop
                 .Add(x => x.Form.Description, x => x.FormName)
                 .Add(x => x.FormCompleted, x => x.Completed)
                 .Add(x => x.FormCompletedBy.UserID, x => x.CompletedBy)
-                .Add(x => x.FormProcessed, x => x.Processed);
+                .Add(x => x.FormProcessed, x => x.Processed)
+                .Add(x => x.Parent.ID, x => x.ParentID);
             
             _query = new MultiQuery();
             
@@ -194,7 +199,6 @@ namespace PRSDesktop
                 );
             }
 
-            
             if (modules.Any())
                 column.AddSeparator();
             
@@ -205,8 +209,8 @@ namespace PRSDesktop
                     PRSDesktop.Resources.lock_sml,
                     (row) =>
                     {
-                        var form = Activator.CreateInstance(formType) as IDigitalFormInstance;
-                        form.ID = row.Get<DigitalFormDockModel, Guid>(x => x.ID);
+                        var form = (Activator.CreateInstance(formType) as IDigitalFormInstance)!;
+                        form.ID = row!.Get<DigitalFormDockModel, Guid>(x => x.ID);
                         form.FormProcessed = row.Get<DigitalFormDockModel, DateTime>(x => x.Processed);
                         form.CommitChanges();
                         form.FormProcessed = DateTime.Now;
@@ -225,8 +229,8 @@ namespace PRSDesktop
                     PRSDesktop.Resources.lock_sml,
                     (row) =>
                     {
-                        var form = Activator.CreateInstance(formType) as IDigitalFormInstance;
-                        form.ID = row.Get<DigitalFormDockModel, Guid>(x => x.ID);
+                        var form = (Activator.CreateInstance(formType) as IDigitalFormInstance)!;
+                        form.ID = row!.Get<DigitalFormDockModel, Guid>(x => x.ID);
                         form.FormProcessed = row.Get<DigitalFormDockModel, DateTime>(x => x.Processed);
                         form.CommitChanges();
                         form.FormProcessed = DateTime.MinValue;
@@ -239,6 +243,107 @@ namespace PRSDesktop
                 );
             }
 
+            var entityType = DFUtils.FormEntityType(formType);
+            if(entityType.HasInterface<IJobScopedItem>())
+            {
+                var entityID = row.Get<DigitalFormDockModel, Guid>(x => x.ParentID);
+                column.AddSeparator();
+                column.AddItem("Set Job", PRSDesktop.Resources.project, (row) =>
+                {
+                    var entity = (Client.Create(entityType)
+                        .Query(
+                            Filter.Create<Entity>(entityType, x => x.ID).IsEqualTo(entityID),
+                            LookupFactory.DefineFilterColumns(typeof(Job), entityType)
+                                .Add<Entity>(x => x.ID)
+                                .Add<IJobScopedItem>(x => x.JobLink.ID)
+                                .Add<IJobScopedItem>(x => x.JobLink.JobNumber))
+                        .ToObjects(entityType).First() as Entity)!;
+                    var item = (entity as IJobScopedItem)!;
+                    
+                    var window = new MultiSelectDialog<Job>(
+                        LookupFactory.DefineFilter<Job>(entityType, CoreUtils.One(entity)),
+                        new Columns<Job>(x => x.DefaultScope.ID).Add(x => x.JobNumber),
+                        multiselect: false);
+                    if (!window.ShowDialog(nameof(Job.JobNumber), item.JobLink.JobNumber, Syncfusion.Data.FilterType.Equals))
+                    {
+                        return;
+                    }
+                    var job = window.Data().ToObjects<Job>().First();
+                    item.JobLink.ID = job.ID;
+                    item.JobLink.Synchronise(job);
+
+                    Client.Create(entityType).Save(entity, "Linked job set by user from Digital forms dock.");
+                    MessageBox.Show($"{entityType.Name} has been assigned to job {job.JobNumber}.");
+                });
+                column.AddItem("Set Job Scope", PRSDesktop.Resources.project, (row) =>
+                {
+                    var entity = (Client.Create(entityType)
+                        .Query(
+                            Filter.Create<Entity>(entityType, x => x.ID).IsEqualTo(entityID),
+                            LookupFactory.DefineFilterColumns(typeof(JobScope), entityType)
+                                .Add<Entity>(x => x.ID)
+                                .Add<IJobScopedItem>(x => x.JobLink.ID)
+                                .Add<IJobScopedItem>(x => x.JobScope.ID)
+                                .Add<IJobScopedItem>(x => x.JobScope.Number))
+                        .ToObjects(entityType).First() as Entity)!;
+                    var item = (entity as IJobScopedItem)!;
+                    if(item.JobLink.ID == Guid.Empty)
+                    {
+                        MessageBox.Show($"{entityType.Name} is not linked to a job. Please select a job first.");
+                        return;
+                    }
+
+                    var window = new MultiSelectDialog<JobScope>(
+                        new Filters<JobScope>()
+                            .Add(LookupFactory.DefineFilter<JobScope>(entityType, CoreUtils.One(entity)))
+                            .Add(new Filter<JobScope>(x => x.Job.ID).IsEqualTo(item.JobLink.ID))
+                            .Combine(),
+                        new Columns<JobScope>(x => x.ID).Add(x => x.Number),
+                        multiselect: false);
+                    if (!window.ShowDialog(nameof(JobScope.Number), item.JobScope.Number, Syncfusion.Data.FilterType.Equals))
+                    {
+                        return;
+                    }
+                    var scope = window.Data().ToObjects<JobScope>().First();
+                    item.JobScope.ID = scope.ID;
+
+                    Client.Create(entityType).Save(entity, "Linked scope set by user from Digital forms dock.");
+                    MessageBox.Show($"{entityType.Name} has been assigned to scope {scope.Number}.");
+                });
+            }
+            else if(entityType == typeof(Job) && formType == typeof(JobForm))
+            {
+                column.AddSeparator();
+                column.AddItem("Set Job Scope", PRSDesktop.Resources.project, (row) =>
+                {
+                    var instance = Client.Query(
+                        new Filter<JobForm>(x => x.ID).IsEqualTo(instanceID),
+                        LookupFactory.DefineFilterColumns<JobForm, JobScope>()
+                            .Add(x => x.ID)
+                            .Add(x => x.Parent.ID))
+                        .ToObjects<JobForm>().First();
+                    var job = Client.Query(
+                        new Filter<Job>(x => x.ID).IsEqualTo(instance.Parent.ID),
+                        LookupFactory.DefineFilterColumns<Job, JobScope>()).ToObjects<Job>().First();
+
+                    var window = new MultiSelectDialog<JobScope>(
+                        new Filters<JobScope>()
+                            .Add(LookupFactory.DefineFilter<Job, JobScope>(new Job[] { job }))
+                            .Add(new Filter<JobScope>(x => x.Job.ID).IsEqualTo(instance.Parent.ID))
+                            .Combine(),
+                        new Columns<JobScope>(x => x.ID).Add(x => x.Number), multiselect: false);
+                    if (!window.ShowDialog())
+                    {
+                        return;
+                    }
+                    var scope = window.Data().ToObjects<JobScope>().First();
+                    instance.JobScope.ID = scope.ID;
+
+                    Client.Save(instance, "Linked scope set by user from Digital forms dock.");
+                    MessageBox.Show($"Form has been assigned to scope {scope.Number}.");
+                });
+            }
+
 
             if (Security.IsAllowed<CanCustomiseModules>())
             {
@@ -263,6 +368,165 @@ namespace PRSDesktop
             }
         }
 
+        /*private void AttachToScope(CoreRow row, Type formType, DataModel model)
+        {
+            var instance = Client.Create(formType)
+                .Query(
+                    Filter.Create<IDigitalFormInstance>(formType, x => x.ID).IsEqualTo(row.Get<DigitalFormDockModel, Guid>(x => x.ID)),
+                    Columns.Create<IDigitalFormInstance>(formType)
+                        .Add<IDigitalFormInstance>(x => x.ID)
+                        .Add<IDigitalFormInstance>(x => x.Number))
+                .Rows.FirstOrDefault()
+                ?.ToObject(formType) as IDigitalFormInstance;
+            if (instance is null)
+            {
+                MessageBox.Show("Form does not exist!");
+                return;
+            }
+            var formID = row.Get<DigitalFormDockModel, Guid>(x => x.FormID);
+
+            var entityColumns = JobScopeForms.GetEntityColumns(formType)?.Add<Entity>(x => x.ID);
+            var entityObj = Client.Create(instance.ParentType())
+                .Query(
+                    Filter.Create<Entity>(instance.ParentType(), x => x.ID).IsEqualTo(row.Get<DigitalFormDockModel, Guid>(x => x.ParentID)),
+                    entityColumns).ToObjects(instance.ParentType()).FirstOrDefault();
+            if (entityObj is not Entity entity)
+            {
+                MessageBox.Show($"Attached {instance.ParentType().Name} does not exist!");
+                return;
+            }
+
+            #region Selecting Scope
+
+            // JobScopes obviously can't have an empty ID, so it's fine that I turn null into Guid.Empty here.
+            var scopeID = JobScopeForms.GetJobScopeID(formType, instance, entity) ?? Guid.Empty;
+            if(scopeID == Guid.Empty)
+            {
+                // JobScopes can't have an empty job, so it's fine that I turn null into Guid.Empty here.
+                var jobID = JobScopeForms.GetJobID(formType, instance, entity) ?? Guid.Empty;
+                if(jobID == Guid.Empty)
+                {
+                    var jobs = new MultiSelectDialog<Job>(null, null, multiselect: false);
+                    if(!jobs.ShowDialog("Select a job"))
+                    {
+                        MessageBox.Show("No job selected; process cancelled.");
+                        return;
+                    }
+                    jobID = jobs.IDs().First();
+                }
+
+                var scopes = new MultiSelectDialog<JobScope>(new Filter<JobScope>(x => x.Job.ID).IsEqualTo(jobID), null, multiselect: false);
+                if (!scopes.ShowDialog("Select a scope"))
+                {
+                    MessageBox.Show("Process cancelled.");
+                    return;
+                }
+                scopeID = scopes.IDs().First();
+            }
+
+            var scopeTask = Task.Run(() => Client.QueryMultiple(
+                new KeyedQueryDef<JobScope>(
+                    new Filter<JobScope>(x => x.ID).IsEqualTo(scopeID),
+                    new Columns<JobScope>(x => x.ID).Add(x => x.Number)),
+                new KeyedQueryDef<Job>(
+                    new Filter<Job>(x => x.ID).InQuery(new Filter<JobScope>(x => x.ID).IsEqualTo(scopeID), x => x.Job.ID),
+                    new Columns<Job>(x => x.JobNumber))));
+
+            #endregion
+
+            #region Selecting Report
+
+            var reports = new List<ReportTemplate>();
+            Progress.ShowModal("Loading Document", (progress) =>
+            {
+                reports = ReportUtils.LoadReports(formID.ToString(), model).ToList();
+            });
+
+            ReportTemplate report;
+            if (reports.Count == 0)
+            {
+                ReportTemplate reportTemplate = null!;
+                Progress.ShowModal("Loading form layout", (progress) =>
+                {
+                    progress.Report("Loading form layout");
+                    var layouts = Client.Query(
+                        new Filter<DigitalFormLayout>(x => x.Form.ID).IsEqualTo(formID),
+                        new Columns<DigitalFormLayout>(x => x.Layout)
+                            .Add(x => x.Code)
+                            .Add(x => x.Type)
+                            .Add(x => x.Description))
+                        .ToObjects<DigitalFormLayout>().ToArray();
+                    var layout = layouts.FirstOrDefault(x => x.Type == DFLayoutType.Desktop) ?? layouts.FirstOrDefault();
+                    if (layout is null)
+                    {
+                        MessageBox.Show("This form has no report or layout, so it cannot be attached to a job scope!");
+                        return;
+                    }
+
+                    progress.Report("Generating report");
+
+                    report = new ReportTemplate
+                    {
+                        DataModel = model.Name,
+                        Name = layout.Description.NotWhiteSpaceOr(layout.Code),
+                        RDL = DigitalFormUtils.GenerateReport(layout, model)?.SaveToString()
+                    };
+                });
+                report = reportTemplate;
+            }
+            else if (reports.Count == 1)
+            {
+                report = reports[0];
+            }
+            else
+            {
+                var selectedReports = new MultiSelectDialog<ReportTemplate>(
+                    ReportUtils.GetReportFilter(formID.ToString(), model),
+                    null,
+                    multiselect: false);
+                if (!selectedReports.ShowDialog())
+                {
+                    return;
+                }
+                report = selectedReports.Items().First();
+            }
+
+            #endregion
+
+            Document document = null!;
+
+            Progress.ShowModal("Loading Document", (progress) =>
+            {
+                progress.Report("Generating Document");
+
+                var data = ReportUtils.ReportToPDF(report, model, true);
+
+                progress.Report("Saving Document");
+
+                document = new Document
+                {
+                    FileName = $"{instance.Number}: {report.Name}.pdf",
+                    Data = data,
+                    CRC = CoreUtils.CalculateCRC(data)
+                };
+                Client.Save(document, "");
+
+                progress.Report("Creating Job Scope Document");
+
+                var jobScopeDocument = new JobScopeDocument();
+                jobScopeDocument.DocumentLink.ID = document.ID;
+                jobScopeDocument.EntityLink.ID = scopeID;
+                Client.Save(jobScopeDocument, $"Generated from form: {instance.Number}");
+            });
+
+            scopeTask.Wait();
+            var scopeResults = scopeTask.Result;
+            var scope = scopeResults.GetObjects<JobScope>().First();
+            var job = scopeResults.GetObjects<Job>().First();
+
+            MessageBox.Show($"Attached as '{document.FileName}' to job scope {scope.Number} for job {job.JobNumber}");
+        }*/
+
         private DynamicMenuStatus MenuStatus(CoreRow row)
         {
             if (row == null) return DynamicMenuStatus.Hidden;
@@ -281,6 +545,7 @@ namespace PRSDesktop
 
                 var cols = Columns.Create<IDigitalFormInstance>(type)
                     .Add<IDigitalFormInstance>(c => c.ID)
+                    .Add<IDigitalFormInstance>(c => c.Parent.ID)
                     .Add<IDigitalFormInstance>(c => c.Form.ID)
                     .Add<IDigitalFormInstance>(c => c.Number)
                     .Add<IDigitalFormInstance>(c => c.Form.Description)