|  | @@ -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)
 |