소스 검색

(DO NOT MERGE YET - INCOMPLETE )PRS DESKTOP / CLASSES - Staging classes for importing setout PDFS

Nick-PRSDigital@bitbucket.org 1 년 전
부모
커밋
5d8291549b

+ 46 - 0
prs.classes/Entities/Staging/Manufacturing/StagingManufacturingPacket.cs

@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using InABox.Core;
+
+namespace Comal.Classes
+{
+    public class StagingManufacturingPacket : Entity, IPersistent, IRemotable, IOneToMany<StagingSetout>
+    {
+        [TextBoxEditor]
+        public string Title { get; set; }
+
+        [CodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)]
+        public string Serial { get; set; }
+
+        public JobLink Job { get; set; }
+        public JobITPLink JobITP { get; set; }
+
+        [NullEditor]
+        public StagingSetoutLink StagingSetout { get; set; }
+
+        public StagingManufacturingWatermarkLink Watermark { get; set; }
+
+        [TextBoxEditor]
+        public string Location { get; set; }
+
+        public double Quantity { get; set; }
+
+        [NullEditor]
+        public ManufacturingPacketLink ManufacturingPacket { get; set; }
+
+
+        protected override void Init()
+        {
+            Title = "";
+            StagingSetout = new StagingSetoutLink();
+            JobITP = new JobITPLink();
+            Serial = "";
+            Watermark = new StagingManufacturingWatermarkLink();
+            ManufacturingPacket = new ManufacturingPacketLink();
+            Job = new JobLink();
+            base.Init();
+        }
+
+    }
+}

+ 18 - 0
prs.classes/Entities/Staging/Manufacturing/StagingManufacturingWatermark.cs

@@ -0,0 +1,18 @@
+using InABox.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Comal.Classes
+{
+    public class StagingManufacturingWatermark : Entity, IRemotable, IPersistent
+    {
+        [CodeEditor(Editable = Editable.Enabled)]
+        public string Watermark { get; set; }
+        protected override void Init()
+        {
+            Watermark = "";
+            base.Init();
+        }
+    }
+}

+ 21 - 0
prs.classes/Entities/Staging/Manufacturing/StagingManufacturingWatermarkLink.cs

@@ -0,0 +1,21 @@
+using InABox.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Comal.Classes
+{
+    public class StagingManufacturingWatermarkLink : EntityLink<StagingManufacturingWatermark>
+    {
+        [LookupEditor(typeof(StagingManufacturingWatermark))]
+        public override Guid ID { get; set; }
+
+        [CodeEditor(Editable = Editable.Enabled)]
+        public string Watermark { get; set; }
+        protected override void Init()
+        {
+            Watermark = "";
+            base.Init();
+        }
+    }
+}

+ 14 - 3
prs.classes/StagingSetout.cs → prs.classes/Entities/Staging/Setout/StagingSetout.cs

@@ -7,16 +7,27 @@ namespace Comal.Classes
 {
     public class StagingSetout : Entity, IPersistent, IRemotable
     {
-        [UniqueCodeEditor(Visible = Visible.Default, Editable = Editable.Disabled)]
+        [TextBoxEditor(Editable = Editable.Disabled)]
         public string Number { get; set; }
 
-        [NullEditor]
         public JobLink JobLink { get; set; }
+
+        [NullEditor]
         public SetoutLink Setout { get; set; }
 
-        public StagingSetout()
+        [DateTimeEditor(Editable =Editable.Disabled)]
+        public DateTime Archived { get; set; }
+
+        [NullEditor]
+        public KanbanLink Task { get; set; }
+
+        protected override void Init()
         {
+            Number = "";
             JobLink = new JobLink();
+            Setout = new SetoutLink();
+            Task = new KanbanLink();
+            base.Init();
         }
     }
 }

+ 11 - 0
prs.classes/Entities/Staging/Setout/StagingSetoutDocument.cs

@@ -0,0 +1,11 @@
+using InABox.Core;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Comal.Classes
+{
+    public class StagingSetoutDocument : EntityDocument<StagingSetoutLink>, IManyToMany<StagingSetout, Document>
+    {
+    }
+}

+ 2 - 2
prs.classes/StagingSetoutLink.cs → prs.classes/Entities/Staging/Setout/StagingSetoutLink.cs

@@ -7,7 +7,6 @@ namespace Comal.Classes
 {
     public class StagingSetoutLink : EntityLink<StagingSetout>
     {
-        [SecondaryIndex]
         [LookupEditor(typeof(StagingSetout))]
         public override Guid ID { get; set; }
 
@@ -17,9 +16,10 @@ namespace Comal.Classes
         [NullEditor]
         public JobLink JobLink { get; set; }
 
-        public StagingSetoutLink()
+        protected override void Init()
         {
             JobLink = new JobLink();
+            base.Init();
         }
     }
 }

+ 0 - 10
prs.classes/StagingSetoutDocument.cs

@@ -1,10 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Comal.Classes
-{
-    internal class StagingSetoutDocument
-    {
-    }
-}

+ 173 - 0
prs.desktop/Grids/StagingSetoutGrid.cs

@@ -0,0 +1,173 @@
+using Comal.Classes;
+using InABox.Clients;
+using InABox.Core;
+using InABox.DynamicGrid;
+using javax.print.attribute.standard;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace PRSDesktop
+{
+    public class StagingSetoutGrid : DynamicDataGrid<StagingSetout>
+    {
+        List<string> _existingFileNames = new List<string>();
+        List<Job> _jobs = new List<Job>();
+
+        public StagingSetoutGrid()
+        {
+            HiddenColumns.Add(x => x.Setout.ID);
+            HiddenColumns.Add(x => x.JobLink.ID);
+            Options.Add(DynamicGridOption.FilterRows);
+            Options.Add(DynamicGridOption.SelectColumns);
+            Options.Add(DynamicGridOption.RecordCount);
+
+            LoadJobs();
+
+            ScanFiles();
+        }
+
+        private void LoadJobs()
+        {
+            CoreTable table = new Client<Job>().Query(null, new Columns<Job>(x => x.ID, x => x.JobNumber, x => x.Name));
+            if (table.Rows.Any())
+                foreach (CoreRow row in table.Rows)
+                    _jobs.Add(row.ToObject<Job>());
+        }
+
+        public void ScanFiles()
+        {
+            IEnumerable<FileInfo> files = GetFiles();
+
+            LoadExistingStaging();
+
+            List<Document> documents = new List<Document>();
+            List<StagingSetoutDocument> stagingdocs = new List<StagingSetoutDocument>();
+
+            foreach (var file in files)
+            {
+                if (!file.FullName.EndsWith(".pdf"))
+                    continue;
+
+                if (CheckStagingSetoutExists(file))
+                    continue;
+
+                documents.Add(ReadFile(file));
+            }
+
+            new Client<Document>().Save(documents, "Created from sync setout function");
+
+            var messages = new List<string>();
+            foreach (var doc in documents)
+            {
+                var stagingsetout = new StagingSetout();
+                stagingsetout.Number = doc.FileName.Substring(0, doc.FileName.Length - 4);
+                stagingsetout.JobLink.ID = FindJob(doc.FileName.Substring(0, 4));
+                new Client<StagingSetout>().Save(stagingsetout, "Created from sync setout function");
+
+                var stagingsetoutdoc = new StagingSetoutDocument();
+                stagingsetoutdoc.EntityLink.ID = stagingsetout.ID;
+                stagingsetoutdoc.DocumentLink.ID = doc.ID;
+                stagingdocs.Add(stagingsetoutdoc);
+
+                if (stagingsetout.JobLink.ID == Guid.Empty)
+                    messages.Add(doc.FileName);
+            }
+
+            if (messages.Any())
+                MessageBox.Show("Job(s) not found for the following document(s): " + string.Join("," + Environment.NewLine, messages), "Warning");
+
+            new Client<StagingSetoutDocument>().Save(stagingdocs, "Created from sync setout function");
+        }
+
+        private Guid FindJob(string filePreFix)
+        {
+            var job = _jobs.FirstOrDefault(x => x.JobNumber.Equals(filePreFix));
+            if (job == null)
+                return Guid.Empty;
+
+            else
+                return job.ID;
+        }
+
+        private Document ReadFile(FileInfo file)
+        {
+            Document doc = new Document();
+            doc.FileName = file.Name;
+            doc.Data = GetData(file);
+            return doc;
+        }
+
+        private byte[] GetData(FileInfo file)
+        {
+            Stream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
+            byte[] pdfData = new byte[stream.Length];
+            stream.Read(pdfData, 0, System.Convert.ToInt32(pdfData.Length));
+            stream.Dispose();
+            return pdfData;
+        }
+
+        private IEnumerable<FileInfo> GetFiles()
+        {
+            string folder = @"U:\" + "9999" + " " + "Test Job" + @"\COM-AL SETOUTS";
+            var dir = new DirectoryInfo(folder);
+
+            //return dir.EnumerateFiles();
+            return dir.GetFiles();
+        }
+
+        public void ReloadFile(IEntityDocument document)
+        {
+            var files = GetFiles();
+            foreach (var file in files)
+            {
+                if (file.Name == document.DocumentLink.FileName)
+                {
+                    CoreTable table = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(document.DocumentLink.ID));
+                    var doc = table.Rows.FirstOrDefault().ToObject<Document>();
+                    doc.Data = GetData(file);
+                    new Client<Document>().Save(doc, "Reloaded Marked up Document");
+                    return;
+                }
+            }
+        }
+
+        private void LoadExistingStaging()
+        {
+            CoreTable stagingseouttable = new Client<StagingSetout>().Query(
+                new Filter<StagingSetout>(x => x.Archived).IsEqualTo(DateTime.MinValue),
+                new Columns<StagingSetout>(x => x.Number));
+            var ids = new List<Guid>();
+            foreach (var row in stagingseouttable.Rows)
+                _existingFileNames.Add(row.Get<StagingSetout, string>(x => x.Number));
+        }
+
+        private bool CheckStagingSetoutExists(FileInfo file)
+        {
+            foreach (var existing in _existingFileNames)
+            {
+                if (file.Name.Substring(0, file.Name.Length - 4).Equals(existing))
+                    return true;
+            }
+
+            return false;
+        }
+
+        protected override void Reload(Filters<StagingSetout> criteria, Columns<StagingSetout> columns, ref SortOrder<StagingSetout>? sort, Action<CoreTable?, Exception?> action)
+        {
+            criteria.Add(new Filter<StagingSetout>(x => x.Archived).IsEqualTo(DateTime.MinValue));
+            base.Reload(criteria, columns, ref sort, action);
+        }
+
+        public void DeleteFile(IEntityDocument document)
+        {
+            var file = GetFiles().FirstOrDefault(x => x.Name == document.DocumentLink.FileName);
+            if (file != null)
+                file.Delete();
+        }
+    }
+}

+ 2 - 2
prs.desktop/MainWindow.xaml

@@ -333,8 +333,8 @@
                     <fluent:Button x:Name="ProjectPlannerButton" Header="Project Planner"
                                    LargeIcon="pack://application:,,,/Resources/calendar.png"
                                    Click="ProjectPlanner_Checked" MinWidth="60" />
-                    <fluent:Button x:Name="SetoutImportButton" Header="Project Planner"
-                                   LargeIcon="pack://application:,,,/Resources/pdficon.png"
+                    <fluent:Button x:Name="SetoutImportButton" Header="Design Management"
+                                   LargeIcon="pack://application:,,,/Resources/design.png"
                                    Click="SetoutImport_Checked" MinWidth="60" />
                     <fluent:Button x:Name="ServiceButton" Header="Service"
                                    LargeIcon="pack://application:,,,/Resources/service.png"

+ 16 - 4
prs.desktop/MainWindow.xaml.cs

@@ -695,7 +695,11 @@ namespace PRSDesktop
                             
                         AddSetupSeparator(ProjectsTab);
                         AddSetupAction(ProjectsTab, "Spreadsheet Templates", () => ViewSpreadsheetTemplates<Job>(), PRSDesktop.Resources.box,
-                            Security.CanView<JobSpreadsheet>());   
+                            Security.CanView<JobSpreadsheet>());
+
+                        AddSetupSeparator(ProjectsTab);
+                        AddSetupAction(ProjectsTab, "Manufacturing Watermarks", ViewWaterMarks, PRSDesktop.Resources.design,
+                            Security.IsAllowed<CanConfigureFactoryFloor>());
 
                         AddSetupModulesAndReports(ProjectsTab);
 
@@ -1959,6 +1963,11 @@ namespace PRSDesktop
             LoadWindow<JobResourcePlannerPanel>((Fluent.Button)sender);
         }
 
+        private void SetoutImport_Checked(object sender, RoutedEventArgs e)
+        {
+            LoadWindow<StagingPanel>((Fluent.Button)sender);
+        }
+
         private void Service_Checked(object sender, RoutedEventArgs e)
         {
             MessageBox.Show("Not Implemented");
@@ -2077,6 +2086,12 @@ namespace PRSDesktop
             list.ShowDialog();
         }
 
+        private void ViewWaterMarks()
+        {
+            var list = new MasterList(typeof(StagingManufacturingWatermark));
+            list.ShowDialog();
+        }
+
 
         private void RolesSetup_Click()
         {
@@ -4171,9 +4186,6 @@ namespace PRSDesktop
 
         #endregion
 
-        private void SetoutImport_Checked(object sender, RoutedEventArgs e)
-        {
 
-        }
     }
 }

+ 27 - 0
prs.desktop/ManufacturingPacketApprovalControl.xaml

@@ -0,0 +1,27 @@
+<UserControl x:Class="PRSDesktop.ManufacturingPacketApprovalControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PRSDesktop"
+             xmlns:dynamicgrid="clr-namespace:InABox.DynamicGrid;assembly=InABox.Wpf"
+             xmlns:wpf="clr-namespace:InABox.Wpf;assembly=InABox.Wpf" xmlns:local1="clr-namespace:PRSDesktop.Panels.Staging"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800">
+
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="*"/>
+            <RowDefinition Height="*"/>
+        </Grid.RowDefinitions>
+
+        <Border Grid.Row="0" BorderBrush="Gray" BorderThickness="0.5">
+            <local1:StagingManufacturingPacketGrid Grid.Row="1" x:Name="packetGrid"/>
+        </Border>
+
+        <Border Grid.Row="1">
+
+        </Border>
+
+    </Grid>
+</UserControl>

+ 51 - 0
prs.desktop/ManufacturingPacketApprovalControl.xaml.cs

@@ -0,0 +1,51 @@
+using Comal.Classes;
+using PRSDesktop.Panels.Staging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PRSDesktop
+{
+    /// <summary>
+    /// Interaction logic for ManufacturingPacketApprovalControl.xaml
+    /// </summary>
+    public partial class ManufacturingPacketApprovalControl : UserControl
+    {
+        private StagingSetout stagingsetout;
+        public StagingSetout StagingSetout
+        {
+            get => stagingsetout;
+            set
+            {
+                stagingsetout = value;
+                packetGrid.StagingSetout = value;
+            }
+        }
+        public ManufacturingPacketApprovalControl()
+        {
+            InitializeComponent();
+        }
+
+        private void CreatePacketButton_Click(object sender, RoutedEventArgs e)
+        {
+            var packet = new StagingManufacturingPacket();
+            packet.StagingSetout.ID = stagingsetout.ID;
+            packet.Job.ID = stagingsetout.JobLink.ID;
+
+            var page = new StagingManufacturingPacketGrid();
+            if (page.EditItems(new[] { packet }))
+                packetGrid.Refresh(false, true);
+        }
+    }
+}

+ 6 - 2
prs.desktop/Panels/Meeting/MeetingPanel.xaml.cs

@@ -266,10 +266,14 @@ namespace PRSDesktop
             }
 
         }
-        
-        #endregion
 
 
 
+        #endregion
+
+        private void Meetings_OnCustomiseEditor(IDynamicEditorForm sender, Meeting items, DynamicGridColumn column, BaseEditor editor)
+        {
+
+        }
     }
 }

+ 72 - 0
prs.desktop/Panels/Staging/StagingManufacturingPacketGrid.cs

@@ -0,0 +1,72 @@
+using Comal.Classes;
+using InABox.Core;
+using InABox.DynamicGrid;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+
+namespace PRSDesktop.Panels.Staging
+{
+    public class StagingManufacturingPacketGrid : DynamicDataGrid<StagingManufacturingPacket>
+    {
+        private StagingSetout stagingsetout;
+
+        public StagingSetout StagingSetout
+        {
+            get => stagingsetout;
+            set 
+            {
+                stagingsetout = value;
+                Refresh(true, true);
+                if (stagingsetout.ID != Guid.Empty)
+                    Options.Add(DynamicGridOption.AddRows);
+                else
+                    Options.Remove(DynamicGridOption.AddRows);
+            }
+        }
+
+        public StagingManufacturingPacketGrid()
+        {
+            Options.Add(DynamicGridOption.SelectColumns);
+            Options.Add(DynamicGridOption.RecordCount);
+            Options.Add(DynamicGridOption.DeleteRows);
+            Options.Remove(DynamicGridOption.AddRows);
+            Options.Remove(DynamicGridOption.MultiSelect);
+            Options.Remove(DynamicGridOption.ImportData);      
+
+
+        }
+
+        protected override StagingManufacturingPacket CreateItem()
+        {
+            var item = base.CreateItem();
+            item.StagingSetout.ID = stagingsetout.ID;
+            item.Job.ID = stagingsetout.JobLink.ID;
+            item.Serial = stagingsetout.Number;
+
+            return item;
+        }
+
+
+
+        private bool CreatePacket(Button arg1, CoreRow[] arg2)
+        {
+            var page = new StagingManufacturingPacketGrid();
+            var packet = new StagingManufacturingPacket();
+            packet.StagingSetout.ID = StagingSetout.ID;
+            packet.Job.ID = StagingSetout.JobLink.ID;
+            page.EditItems(new[] { packet} );
+
+            return true;
+        }
+
+        protected override void Reload(Filters<StagingManufacturingPacket> criteria, Columns<StagingManufacturingPacket> columns, ref SortOrder<StagingManufacturingPacket>? sort, Action<CoreTable?, Exception?> action)
+        {
+            criteria.Add(new Filter<StagingManufacturingPacket>(x => x.StagingSetout.ID).IsEqualTo(StagingSetout.ID));
+            base.Reload(criteria, columns, ref sort, action);
+        }
+    }
+}

+ 34 - 7
prs.desktop/Panels/Staging/StagingPanel.xaml

@@ -4,21 +4,48 @@
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:dynamicgrid="clr-namespace:InABox.DynamicGrid;assembly=InABox.Wpf"
-             xmlns:local="clr-namespace:PRSDesktop"
+             xmlns:local="clr-namespace:PRSDesktop" xmlns:wpf="clr-namespace:InABox.Wpf;assembly=InABox.Wpf"
              mc:Ignorable="d" 
              d:DesignHeight="450" d:DesignWidth="800">
 
-    <dynamicgrid:DynamicSplitPanel x:Name="mainPanel" View="Combined" MasterCaption="Setouts Folder">
+    <dynamicgrid:DynamicSplitPanel x:Name="mainPanel" View="Combined" MasterCaption="Setouts Folder" AnchorWidth="250">
 
         <dynamicgrid:DynamicSplitPanel.Master>
-            
+            <local:StagingSetoutGrid x:Name="stagingSetoutGrid"/>
         </dynamicgrid:DynamicSplitPanel.Master>
-        
+
         <dynamicgrid:DynamicSplitPanel.Detail>
-            <dynamicgrid:DynamicSplitPanel x:Name="nestedPanel">
-                
+            <dynamicgrid:DynamicSplitPanel x:Name="nestedPanel" View="Combined" AnchorWidth="1000" MasterCaption="PDF">
+                <dynamicgrid:DynamicSplitPanel.Master>
+                    <Border Grid.Row="0" BorderBrush="Gray" BorderThickness="0.5">
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="auto"/>
+                                <RowDefinition Height="*"/>
+                            </Grid.RowDefinitions>
+                            <Border Grid.Row="0" BorderBrush="Gray" BorderThickness="0.5">
+                                <Label Content="Document Viewer" HorizontalAlignment="Center" FontWeight="DemiBold"/>
+                            </Border>
+                            <wpf:DocumentApprovalControl x:Name="documentPreviewer" Width="1000" Grid.Row="1"/>
+                        </Grid>
+                    </Border>
+                </dynamicgrid:DynamicSplitPanel.Master>
+
+                <dynamicgrid:DynamicSplitPanel.Detail>
+                    <Border BorderBrush="Gray" BorderThickness="0.5">
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="auto"/>
+                                <RowDefinition Height="*"/>
+                            </Grid.RowDefinitions>
+                            <Label Grid.Row="0" Content="Manufacturing Packets" FontWeight="DemiBold" HorizontalAlignment="Center"/>
+                            <local:ManufacturingPacketApprovalControl Grid.Row="1" x:Name="manufacturingControl"/>
+                        </Grid>
+                    </Border>
+                </dynamicgrid:DynamicSplitPanel.Detail>
+
             </dynamicgrid:DynamicSplitPanel>
         </dynamicgrid:DynamicSplitPanel.Detail>
     </dynamicgrid:DynamicSplitPanel>
-    
+
 </UserControl>

+ 178 - 2
prs.desktop/Panels/Staging/StagingPanel.xaml.cs

@@ -1,4 +1,7 @@
-using System;
+using com.sun.security.ntlm;
+using Comal.Classes;
+using InABox.Core;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -12,17 +15,190 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
+using InABox.Client;
+using InABox.Clients;
+using Syncfusion.UI.Xaml.Kanban;
 
 namespace PRSDesktop
 {
     /// <summary>
     /// Interaction logic for StagingPanel.xaml
     /// </summary>
-    public partial class StagingPanel : UserControl
+    public partial class StagingPanel : UserControl, IPanel<StagingSetout>
     {
+        StagingSetout _item = new StagingSetout();
         public StagingPanel()
         {
             InitializeComponent();
+            SectionName = nameof(StagingPanel);
+            stagingSetoutGrid.Refresh(true, true);
+            stagingSetoutGrid.OnSelectItem += StagingSetoutGrid_OnSelectItem;
+
+            documentPreviewer.SetupButtons(/*approveVisible: false*/);
+            documentPreviewer.OnMarkupComplete += DocumentPreviewer_OnMarkupComplete;    
+            documentPreviewer.OnRejected += DocumentPreviewer_OnRejected;
+            documentPreviewer.OnApproved += DocumentPreviewer_OnApproved;
+        }
+
+        private void DocumentPreviewer_OnMarkupComplete(IEntityDocument document)
+        {
+            stagingSetoutGrid.ReloadFile(document);
+            stagingSetoutGrid.Refresh(false, true);
+        }
+        private void DocumentPreviewer_OnApproved(IEntityDocument stagingsetoutdocument)
+        {
+            var table = new Client<Setout>().Query(new Filter<Setout>(x => x.Number).IsEqualTo(_item.Number),
+                new Columns<Setout>(x => x.ID));
+
+            //setout already exists - create new setoutdoc and supercede old ones
+            if (table.Rows.Any())
+            {
+                if (MessageBox.Show("Supercede existing documents?", "Proceed?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+                {
+                    var setout = table.Rows.FirstOrDefault().ToObject<Setout>();
+
+                    _item.Setout.ID = setout.ID;
+
+                    var setoutdoc = new SetoutDocument();
+                    setoutdoc.EntityLink.ID = setout.ID;
+                    setoutdoc.DocumentLink.ID = stagingsetoutdocument.DocumentLink.ID;
+
+                    List<SetoutDocument> setoutdocs = new List<SetoutDocument>
+                    {
+                        setoutdoc
+                    };
+
+                    CoreTable oldDocsTable = new Client<SetoutDocument>().Query(new Filter<SetoutDocument>(x => x.EntityLink.ID).IsEqualTo(setout.ID));
+                    foreach (var row in oldDocsTable.Rows)
+                    {
+                        var oldDoc = row.ToObject<SetoutDocument>();
+                        if (oldDoc.Superceded == DateTime.MinValue)
+                        {
+                            oldDoc.Superceded = DateTime.Now;
+                            setoutdocs.Add(oldDoc);
+                        }
+                    }
+                    new Client<SetoutDocument>().Save(setoutdocs, "Updated from Staging Screen");
+
+                    MessageBox.Show("Document for setout " + _item.Number + " superceded.", "Success");
+                }
+                else
+                    return;
+            }
+
+            //no setout for this pdf - create new
+            else
+            {
+                var setout = new Setout();
+                setout.Number = _item.Number;
+
+                new Client<Setout>().Save(setout, "Added from staging screen");
+                _item.Setout.ID = setout.ID;
+
+                MessageBox.Show("Setout created for document " + _item.Number, "Success");
+            }
+
+            new Client<StagingSetout>().Save(_item, "Updated from staging screen");
+            _item = new StagingSetout();
+
+            stagingSetoutGrid.DeleteFile(stagingsetoutdocument);
+            documentPreviewer.Document = new StagingSetoutDocument();
+            stagingSetoutGrid.Refresh(false, true);         
+        }
+
+        private void DocumentPreviewer_OnRejected(IEntityDocument stagingsetoutdocument)
+        {
+            //dont create setout - setout.id remains blank
+            //create kanban and populate task.id - this prevents it from appearing on the stagingsetout grid, and allows a new staging setout to be created when the file is saved to the folder again
+            //attach the document to the task for reference
+
+            Kanban task = new Kanban();
+            task.Title = "Setout Review Task (setout rejected)";
+            task.Description = "Please review the attached document for setout " + _item.Number;
+            task.ManagerLink.ID = App.EmployeeID;
+
+            var page = new KanbanGrid();
+            page.MyID = App.EmployeeID;
+
+            page.OnAfterSave += (editor, items) =>
+            {
+                Kanban savedTask = (Kanban)items[0];
+                KanbanDocument doc = new KanbanDocument();
+                doc.EntityLink.ID = savedTask.ID;
+                doc.DocumentLink.ID = stagingsetoutdocument.DocumentLink.ID;
+                new Client<KanbanDocument>().Save(doc, "Created from staging screen");
+
+                _item.Task.ID = savedTask.ID;
+                new Client<StagingSetout>().Save(_item, "Updated from staging screen");
+
+
+                MessageBox.Show("Success - Task Created for Document " + _item.Number + " (Task no. " + savedTask.Number + " assigned to " + savedTask.EmployeeLink.Name + ")");
+                _item = new StagingSetout();
+
+                stagingSetoutGrid.DeleteFile(stagingsetoutdocument);
+                documentPreviewer.Document = new StagingSetoutDocument();
+                stagingSetoutGrid.Refresh(false, true);           
+            };
+
+            if (!page.EditItems(new[] { task }))
+                MessageBox.Show("Task creation cancelled - setout not rejected");
+        }
+
+        private void StagingSetoutGrid_OnSelectItem(object sender, InABox.DynamicGrid.DynamicGridSelectionEventArgs e)
+        {
+            _item = stagingSetoutGrid.SelectedRows.FirstOrDefault().ToObject<StagingSetout>();
+
+            var doc = new Client<StagingSetoutDocument>().Query(
+                new Filter<StagingSetoutDocument>(x => x.EntityLink.ID)
+                .IsEqualTo(_item.ID),
+                new Columns<StagingSetoutDocument>(x => x.ID, x => x.DocumentLink.ID, x => x.DocumentLink.FileName))
+                .Rows.FirstOrDefault().ToObject<StagingSetoutDocument>();
+
+            documentPreviewer.Document = doc;
+            manufacturingControl.StagingSetout = _item;
+        }
+
+        public bool IsReady { get; set; }
+
+        public string SectionName { get; }
+
+
+        public event DataModelUpdateEvent? OnUpdateDataModel;
+
+        public void CreateToolbarButtons(IPanelHost host)
+        {
+
+        }
+
+        public DataModel DataModel(Selection selection)
+        {
+            return new AutoDataModel<StagingSetout>(null);
+        }
+
+        public void Heartbeat(TimeSpan time)
+        {
+
+        }
+
+        public void Refresh()
+        {
+            stagingSetoutGrid.ScanFiles();
+            stagingSetoutGrid.Refresh(false, true);
+        }
+
+        public Dictionary<string, object[]> Selected()
+        {
+            return new();
+        }
+
+        public void Setup()
+        {
+
+        }
+
+        public void Shutdown()
+        {
+
         }
     }
 }

+ 0 - 57
prs.desktop/StagingSetoutGrid.cs

@@ -1,57 +0,0 @@
-using Comal.Classes;
-using InABox.Clients;
-using InABox.Core;
-using InABox.DynamicGrid;
-using javax.print.attribute.standard;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace PRSDesktop
-{
-    public class StagingSetoutGrid : DynamicDataGrid<StagingSetout>
-    {
-        public StagingSetoutGrid() 
-        {
-            CoreTable table = new Client<StagingSetout>().Query(new Filter<StagingSetout>(x => x.Setout.ID).IsEqualTo(Guid.Empty));
-
-            string folder = @"U:\" + "9999" + " " + "Test Job" + @"\COM-AL SETOUTS";
-            var dir = new DirectoryInfo(folder);
-            var files = dir.EnumerateFiles();
-            foreach ( var file in files) 
-            {
-                if (!file.FullName.EndsWith(".pdf"))
-                    continue;
-
-                if (CheckStagingExists(file))
-                    continue;
-
-                Stream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
-                byte[] pdfData = new byte[stream.Length];
-                stream.Read(pdfData, 0, System.Convert.ToInt32(pdfData.Length));
-
-                Document doc = new Document();
-                doc.FileName = file.Name;
-                doc.Data = pdfData;
-
-                new Client<Document>().Save(doc, "Created from sync setout function");             
-            }
-
-        }
-
-        private bool CheckStagingExists(FileInfo file)
-        {
-                
-
-            return true;
-        }
-
-        protected override void Reload(Filters<StagingSetout> criteria, Columns<StagingSetout> columns, ref SortOrder<StagingSetout>? sort, Action<CoreTable?, Exception?> action)
-        {
-            base.Reload(criteria, columns, ref sort, action);
-        }
-    }
-}

+ 1 - 0
prs.stores/PRSStores.projitems

@@ -59,6 +59,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)ScheduleStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)SetoutStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)ShipmentStore.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)StagingSetoutStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)StockAreaStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)StockLocationStore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)StockMovementStore.cs" />

+ 21 - 0
prs.stores/StagingSetoutStore.cs

@@ -0,0 +1,21 @@
+using Comal.Classes;
+using Comal.Stores;
+using NPOI.HSSF.Record;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using InABox.Core;
+
+namespace PRSStores
+{
+    public class StagingSetoutStore : BaseStore<StagingSetout>
+    {
+        protected override void BeforeSave(StagingSetout entity)
+        {
+            if ((entity.Setout.ID != Guid.Empty || entity.Task.ID != Guid.Empty) && entity.Archived == DateTime.MinValue)
+                entity.Archived = DateTime.Now;
+
+            base.BeforeSave(entity);
+        }
+    }
+}