Przeglądaj źródła

Added approval for Staging Manufacuring packets

Kenric Nugteren 1 rok temu
rodzic
commit
4db4b27ff8

+ 24 - 8
prs.classes/Entities/Manufacturing/ManufacturingPacket/IManufacturingPacketGenerator.cs

@@ -2,13 +2,14 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using static System.Collections.Specialized.BitVector32;
 
 namespace Comal.Classes
 {
     /// <summary>
     /// Defines an entity that can be converted into a <see cref="ManufacturingPacketStage"/>.
     /// </summary>
-    public interface IManufacturingPacketGenerator : ISequenceable
+    public interface IManufacturingPacketStageGenerator : ISequenceable
     {
         TimeSpan Time { get; }
 
@@ -18,27 +19,42 @@ namespace Comal.Classes
 
         ManufacturingSectionLink Section { get; }
 
+    }
+
+    public static class IManufacturingPacketGeneratorExtensions
+    {
+        public static Columns<T> GetPacketGeneratorRequiredColumns<T>()
+            where T : IManufacturingPacketStageGenerator
+        {
+            return new Columns<T>(x => x.Time)
+                .Add(x => x.Sequence)
+                .Add(x => x.SequenceType)
+                .Add(x => x.QualityChecks)
+                .Add(x => x.Section.ID)
+                .Add(x => x.Section.Name);
+        }
+
         /// <summary>
         /// Creates a Packet Stage from the Template Stage
         /// You still need to add the Packet.ID
         /// </summary>
         /// <returns></returns>
-        public ManufacturingPacketStage CreateManufacturingPacketStage()
+        public static ManufacturingPacketStage CreateManufacturingPacketStage(this IManufacturingPacketStageGenerator gen)
         {
             var pstage = new ManufacturingPacketStage
             {
-                Time = Time,
-                Sequence = Sequence,
-                SequenceType = SequenceType,
+                Time = gen.Time,
+                Sequence = gen.Sequence,
+                SequenceType = gen.SequenceType,
                 Started = DateTime.MinValue,
                 PercentageComplete = 0.0F,
                 Completed = DateTime.MinValue,
-                QualityChecks = QualityChecks,
+                QualityChecks = gen.QualityChecks,
                 QualityStatus = QualityStatus.NotChecked,
                 QualityNotes = ""
             };
-            pstage.ManufacturingSectionLink.ID = Section.ID;
-            pstage.ManufacturingSectionLink.Name = Section.Name;
+            pstage.ManufacturingSectionLink.ID = gen.Section.ID;
+            pstage.ManufacturingSectionLink.Name = gen.Section.Name;
 
             return pstage;
         }

+ 1 - 1
prs.classes/Entities/Manufacturing/ManufacturingTemplate/ManufacturingTemplateStage.cs

@@ -6,7 +6,7 @@ namespace Comal.Classes
     [Caption("Template Stages")]
     [UserTracking(typeof(ManufacturingPacket))]
     public class ManufacturingTemplateStage : Entity, IRemotable, IPersistent, ISequenceable, IOneToMany<ManufacturingTemplate>,
-        ILicense<ManufacturingLicense>, IManufacturingPacketGenerator
+        ILicense<ManufacturingLicense>, IManufacturingPacketStageGenerator
     {
         [NullEditor]
         [EntityRelationship(DeleteAction.Cascade)]

+ 3 - 4
prs.classes/Entities/Staging/Manufacturing/Packet/StagingManufacturingPacketStage.cs

@@ -5,7 +5,7 @@ using System.Text;
 
 namespace Comal.Classes
 {
-    public class StagingManufacturingPacketStage : Entity, IRemotable, IPersistent, IManufacturingPacketGenerator, ISequenceable
+    public class StagingManufacturingPacketStage : Entity, IRemotable, IPersistent, IManufacturingPacketStageGenerator, ISequenceable
     {
         public StagingManufacturingPacketLink Packet { get; set; }
 
@@ -25,9 +25,7 @@ namespace Comal.Classes
         public long Sequence { get; set; }
 
         [NullEditor]
-        [DoNotPersist]
-        [DoNotSerialize]
-        public string QualityChecks => "";
+        public string QualityChecks { get; set; }
 
         protected override void Init()
         {
@@ -36,6 +34,7 @@ namespace Comal.Classes
             Packet = new StagingManufacturingPacketLink();
             Section = new ManufacturingSectionLink();
             SequenceType = SequenceType.Link;
+            QualityChecks = "";
         }
     }
 }

+ 2 - 2
prs.desktop/Panels/DataEntry/DataEntryList.xaml.cs

@@ -177,7 +177,7 @@ namespace PRSDesktop
 
         private void LoadDocuments(CoreTable? data)
         {
-            var documents = data?.ToObjects<Document>() ?? new Document[] { };
+            var documents = data?.ToObjects<Document>() ?? Array.Empty<Document>();
             var bitmaps = new Dictionary<Guid, List<BitmapImage>>();
             foreach (var document in documents)
             {
@@ -201,7 +201,7 @@ namespace PRSDesktop
                 }
                 else
                 {
-                    images = RenderTextFile(Encoding.UTF8.GetString(document.Data));
+                    images = ImageUtils.RenderTextFileToImages(Encoding.UTF8.GetString(document.Data));
                 }
 
                 foreach (var imageData in images)

+ 16 - 1
prs.desktop/Panels/Staging/Manufacturing/StagingManufacturingPacketList.xaml.cs

@@ -47,7 +47,16 @@ namespace PRSDesktop
                             DynamicGridUtils.LoadEditorColumns<StagingManufacturingPacket>(
                                 new Columns<StagingManufacturingPacket>(x => x.ID)
                                     .Add(x => x.Serial)
-                                    .Add(x => x.Template.Code)));
+                                    .Add(x => x.Title)
+                                    .Add(x => x.Quantity)
+                                    .Add(x => x.BarcodeQuantity)
+                                    .Add(x => x.Watermark)
+                                    .Add(x => x.Location)
+                                    .Add(x => x.ITP.ID)
+                                    .Add(x => x.Job.ID)
+                                    .Add(x => x.Template.ID)
+                                    .Add(x => x.Template.Code)
+                                    .Add(x => x.ManufacturingPacket.ID)));
 
                     ManufacturingPacketList.Children.Clear();
                     foreach(var packet in results.ToObjects<StagingManufacturingPacket>())
@@ -64,6 +73,12 @@ namespace PRSDesktop
             InitializeComponent();
         }
 
+        public IEnumerable<StagingManufacturingPacket> GetPackets()
+        {
+            return ManufacturingPacketList.Children.Cast<StagingManufacturingPacketListItem>()
+                .Select(x => x.Packet);
+        }
+
         private void AddItem(StagingManufacturingPacket packet)
         {
             var item = new StagingManufacturingPacketListItem(packet);

+ 46 - 4
prs.desktop/Panels/Staging/Manufacturing/StagingManufacturingPacketListItem.xaml

@@ -41,20 +41,52 @@
                         Margin="0" Width="30" Height="30"
                         Click="DeleteButton_Click"
                         Background="Transparent" BorderBrush="Transparent">
-                    <Image Source="pack://application:,,,/Resources/delete.png"/>
+                    <Button.Content>
+                        <Image Source="pack://application:,,,/Resources/delete.png"/>
+                    </Button.Content>
+                    <Button.Style>
+                        <Style TargetType="Button">
+                            <Style.Triggers>
+                                <DataTrigger Binding="{Binding Path=ReadOnly,ElementName=Control}" Value="True">
+                                    <Setter Property="Visibility" Value="Collapsed"/>
+                                </DataTrigger>
+                            </Style.Triggers>
+                        </Style>
+                    </Button.Style>
                 </Button>
                 <Button x:Name="EditButton"
                         DockPanel.Dock="Right"
                         Margin="0,0,2,0" Width="30" Height="30"
                         Click="EditButton_Click"
                         Background="Transparent" BorderBrush="Transparent">
-                    <Image Source="pack://application:,,,/Resources/pencil.png"/>
+                    <Button.Content>
+                        <Image Source="pack://application:,,,/Resources/pencil.png"/>
+                    </Button.Content>
+                    <Button.Style>
+                        <Style TargetType="Button">
+                            <Style.Triggers>
+                                <DataTrigger Binding="{Binding Path=ReadOnly,ElementName=Control}" Value="True">
+                                    <Setter Property="Visibility" Value="Collapsed"/>
+                                </DataTrigger>
+                            </Style.Triggers>
+                        </Style>
+                    </Button.Style>
                 </Button>
                 <Button Margin="0,0,2,0" Height="30" Padding="5,0"
                         DockPanel.Dock="Right"
                         x:Name="TemplateButton"
                         MinWidth="110"
-                        Click="TemplateButton_Click"/>
+                        Click="TemplateButton_Click">
+                    <Button.Style>
+                        <Style TargetType="Button">
+                            <Style.Triggers>
+                                <DataTrigger Binding="{Binding Path=ReadOnly,ElementName=Control}" Value="True">
+                                    <Setter Property="IsEnabled" Value="False"/>
+                                </DataTrigger>
+                            </Style.Triggers>
+                        </Style>
+                    </Button.Style>
+                </Button>
                 <TextBox x:Name="SerialBox"
                          TextChanged="SerialBox_TextChanged"
                          LostFocus="SerialBox_LostFocus"
@@ -62,7 +94,17 @@
                          Height="30"
                          Margin="0,0,5,0"
                          VerticalAlignment="Center" VerticalContentAlignment="Center"
-                         DockPanel.Dock="Left"/>
+                         DockPanel.Dock="Left">
+                    <TextBox.Style>
+                        <Style TargetType="TextBox">
+                            <Style.Triggers>
+                                <DataTrigger Binding="{Binding Path=ReadOnly,ElementName=Control}" Value="True">
+                                    <Setter Property="IsEnabled" Value="False"/>
+                                </DataTrigger>
+                            </Style.Triggers>
+                        </Style>
+                    </TextBox.Style>
+                </TextBox>
             </DockPanel>
         </Border>
         <Border Grid.Row="1" BorderBrush="Black" BorderThickness="1,0,1,1" CornerRadius="0,0,3,3"

+ 19 - 0
prs.desktop/Panels/Staging/Manufacturing/StagingManufacturingPacketListItem.xaml.cs

@@ -31,6 +31,10 @@ namespace PRSDesktop
             "Collapsed", typeof(bool), typeof(StagingManufacturingPacketListItem),
             new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnCollapsedChanged)));
 
+        public static readonly DependencyProperty ReadOnlyProperty = DependencyProperty.Register(
+            "ReadOnly", typeof(bool), typeof(StagingManufacturingPacketListItem),
+            new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnReadOnlyChanged)));
+
         /// <summary>
         /// Height of the uncollapsed stages grid.
         /// </summary>
@@ -62,6 +66,12 @@ namespace PRSDesktop
             set => SetValue(StagesGridHeightProperty, value);
         }
 
+        public bool ReadOnly
+        {
+            get => (bool)GetValue(ReadOnlyProperty);
+            set => SetValue(ReadOnlyProperty, value);
+        }
+
         public StagingManufacturingPacketListItem(StagingManufacturingPacket packet)
         {
             Packet = packet;
@@ -88,6 +98,8 @@ namespace PRSDesktop
             {
                 Uncollapse();
             }
+
+            ReadOnly = packet.ManufacturingPacket.ID != Guid.Empty;
         }
 
         private void EditButton_Click(object sender, RoutedEventArgs e)
@@ -240,5 +252,12 @@ namespace PRSDesktop
                 item.Uncollapse();
             }
         }
+
+        private static void OnReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var item = (StagingManufacturingPacketListItem)d;
+            var readOnly = (bool)e.NewValue;
+            item.StagesGrid.ReadOnly = readOnly;
+        }
     }
 }

+ 26 - 1
prs.desktop/Panels/Staging/Manufacturing/StagingManufacturingPacketStageGrid.cs

@@ -14,6 +14,17 @@ namespace PRSDesktop
     {
         public StagingManufacturingPacket Packet { get; set; }
 
+        private bool _readOnly = false;
+        public bool ReadOnly
+        {
+            get => _readOnly;
+            set
+            {
+                _readOnly = value;
+                Reconfigure();
+            }
+        }
+
         public StagingManufacturingPacketStageGrid()
         {
 
@@ -28,7 +39,21 @@ namespace PRSDesktop
         protected override void DoReconfigure(FluentList<DynamicGridOption> options)
         {
             base.DoReconfigure(options);
-            options.AddRange(DynamicGridOption.DirectEdit, DynamicGridOption.SelectColumns);
+            if (ReadOnly)
+            {
+                options.Remove(DynamicGridOption.EditRows);
+                options.Remove(DynamicGridOption.DeleteRows);
+                options.Remove(DynamicGridOption.AddRows);
+                options.Remove(DynamicGridOption.DirectEdit);
+            }
+            else
+            {
+                options.Add(DynamicGridOption.SelectColumns);
+                if (Security.CanEdit<StagingManufacturingPacketStage>())
+                {
+                    options.AddRange(DynamicGridOption.DirectEdit);
+                }
+            }
         }
 
         protected override StagingManufacturingPacketStage CreateItem()

+ 1 - 0
prs.desktop/Panels/Staging/Setouts/StagingSetoutGrid.cs

@@ -270,6 +270,7 @@ namespace PRSDesktop
                 }
                 stagingSetout.SavePath = "";
                 stagingSetout.LockedBy.ID = Guid.Empty;
+                stagingSetout.Locked = DateTime.MinValue;
                 file.Attributes = FileAttributes.Normal;
                 file.Delete();
                 var save = new MultiSave();

+ 46 - 5
prs.desktop/Panels/Staging/StagingPanel.xaml

@@ -9,7 +9,7 @@
              mc:Ignorable="d" 
              d:DesignHeight="450" d:DesignWidth="800">
 
-    <dynamicgrid:DynamicSplitPanel x:Name="mainPanel" View="Combined" AllowableViews="Combined,Detail" MasterCaption="Staged Documents" AnchorWidth="500" Anchor="Master">
+    <dynamicgrid:DynamicSplitPanel x:Name="MainPanel" View="Combined" AllowableViews="Combined,Detail" MasterCaption="Staged Documents" AnchorWidth="500" Anchor="Master">
 
         <dynamicgrid:DynamicSplitPanel.Header>
             <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke">
@@ -30,8 +30,8 @@
         
         <dynamicgrid:DynamicSplitPanel.Detail>
         
-            <dynamicgrid:DynamicSplitPanel x:Name="nestedPanel" View="Master" AllowableViews="Master,Combined" AnchorWidth="500" Anchor="Detail" MasterCaption="Document Viewer" DetailCaption="Manufacturing Packets"
-                                           OnChanged="nestedPanel_OnChanged">
+            <dynamicgrid:DynamicSplitPanel x:Name="NestedPanel" View="Master" AllowableViews="Master,Combined" AnchorWidth="500" Anchor="Detail" MasterCaption="Document Viewer" DetailCaption="Manufacturing Packets"
+                                           OnChanged="NestedPanel_OnChanged">
                 
                 <dynamicgrid:DynamicSplitPanel.Header>
                     <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke">
@@ -41,7 +41,33 @@
                 
                 <dynamicgrid:DynamicSplitPanel.Master>
                     <Border BorderBrush="Gray" BorderThickness="0.75">
-                        <wpf:DocumentApprovalControl x:Name="documentPreviewer" />
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="*"/>
+                                <RowDefinition Height="Auto"/>
+                            </Grid.RowDefinitions>
+                            <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="0">
+                                <StackPanel x:Name="DocumentViewer" Orientation="Vertical" Margin="10"/>
+                            </ScrollViewer>
+                            <Border Grid.Row="1" BorderBrush="Gray" BorderThickness="0.5">
+                                <DockPanel LastChildFill="False">
+                                    <Button DockPanel.Dock="Left"
+                                            Content="Mark Up"
+                                            Padding="20, 5, 20, 5" Margin="5"
+                                            Height="35"
+                                            x:Name="MarkUpButton"
+                                            Click="MarkUpButton_Click"
+                                            IsEnabled="False"/>
+                                    <Button DockPanel.Dock="Right"
+                                            Content="Reject"
+                                            Height="35"
+                                            Padding="20, 5, 20, 5" Margin="5, 5, 15, 5"
+                                            x:Name="RejectButton"
+                                            Click="RejectButton_Click"
+                                            IsEnabled="False"/>
+                                </DockPanel>
+                            </Border>
+                        </Grid>
                     </Border>
                 </dynamicgrid:DynamicSplitPanel.Master>
                 
@@ -67,7 +93,22 @@
                 
                 <dynamicgrid:DynamicSplitPanel.Detail>
                     <Border BorderBrush="Gray" BorderThickness="0.75">
-                        <local:StagingManufacturingPacketList x:Name="ManufacturingPacketList" OnCollapsed="ManufacturingPacketList_OnCollapsed"/>
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="*"/>
+                                <RowDefinition Height="Auto"/>
+                            </Grid.RowDefinitions>
+                            <local:StagingManufacturingPacketList x:Name="ManufacturingPacketList" OnCollapsed="ManufacturingPacketList_OnCollapsed"
+                                                                  Grid.Row="0"/>
+                            <DockPanel LastChildFill="False"
+                                       Grid.Row="1">
+                                <Button DockPanel.Dock="Right"
+                                        Content="Approve"
+                                        x:Name="ApproveButton"
+                                        Height="35" Padding="20,5" Margin="5"
+                                        Click="ApproveButton_Click"/>
+                            </DockPanel>
+                        </Grid>
                     </Border>
                 </dynamicgrid:DynamicSplitPanel.Detail>
 

+ 239 - 96
prs.desktop/Panels/Staging/StagingPanel.xaml.cs

@@ -15,7 +15,6 @@ using System.ComponentModel;
 using InABox.Scripting;
 using System.Reflection;
 using System.Collections.Immutable;
-using com.sun.istack.@internal.localization;
 
 namespace PRSDesktop
 {
@@ -83,6 +82,8 @@ public class Module
         /// </summary>
         private List<StagingSetout> selectedSetouts = new();
 
+        #region Script Stuff
+
         private MethodInfo? _customiseSetoutsMethod;
         private MethodInfo? CustomiseSetoutsMethod
         {
@@ -124,13 +125,115 @@ public class Module
             }
         }
 
+        #endregion
+
         public StagingPanel()
         {
             InitializeComponent();
             SectionName = nameof(StagingPanel);
         }
 
-        private void DocumentPreviewer_OnApproved(IEntityDocument? stagingsetoutdocument)
+        public void Setup()
+        {
+            _settings = new GlobalConfiguration<StagingPanellSettings>().Load();
+
+            MarkUpButton.Visibility = Security.IsAllowed<CanMarkUpSetouts>() ? Visibility.Visible : Visibility.Hidden;
+            RejectButton.Visibility = Security.IsAllowed<CanApproveSetouts>() ? Visibility.Visible : Visibility.Hidden;
+            ApproveButton.Visibility = Security.IsAllowed<CanApproveSetouts>() ? Visibility.Visible : Visibility.Hidden;
+
+            //stagingSetoutGrid.ScanFiles(_settings.SetoutsFolder);
+            stagingSetoutGrid.Refresh(true, true);
+            stagingSetoutGrid.OnSelectItem += StagingSetoutGrid_OnSelectItem;
+        }
+
+        private void NestedPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
+        {
+            if(e.View != DynamicSplitPanelView.Master && ManufacturingPacketList.Setout != selectedSetout)
+            {
+                ManufacturingPacketList.Setout = selectedSetout;
+            }
+        }
+
+        #region Document Viewer
+
+        public enum DocumentMode
+        {
+            Markup,
+            Complete,
+            Locked
+        }
+        private DocumentMode _mode;
+        private DocumentMode Mode
+        {
+            get => _mode;
+            set
+            {
+                _mode = value;
+                if (_mode == DocumentMode.Markup)
+                {
+                    MarkUpButton.Content = "Mark Up";
+                    MarkUpButton.IsEnabled = Document != null;
+                    ApproveButton.IsEnabled = Document != null;
+                    RejectButton.IsEnabled = Document != null;
+                }
+                else if (_mode == DocumentMode.Complete)
+                {
+                    MarkUpButton.Content = "Complete";
+                    MarkUpButton.IsEnabled = Document != null;
+                    ApproveButton.IsEnabled = false;
+                    RejectButton.IsEnabled = false;
+                }
+                else if (_mode == DocumentMode.Locked)
+                {
+                    MarkUpButton.Content = "Locked";
+                    MarkUpButton.IsEnabled = false;
+                    ApproveButton.IsEnabled = false;
+                    RejectButton.IsEnabled = false;
+                }
+            }
+        }
+
+        private StagingSetoutDocument? _document;
+        private StagingSetoutDocument? Document
+        {
+            get => _document;
+            set
+            {
+                if(_document != value)
+                {
+                    _document = value;
+                    RenderDocument(value);
+                }
+            }
+        }
+
+        private void RenderDocument(StagingSetoutDocument? document)
+        {
+            DocumentViewer.Children.Clear();
+            if (document is null)
+            {
+                return;
+            }
+
+            var table = new Client<Document>().Query(
+                new Filter<Document>(x => x.ID).IsEqualTo(document.DocumentLink.ID),
+                new Columns<Document>(x => x.Data));
+            var first = table.Rows.FirstOrDefault();
+            if (first is null)
+                return;
+            var data = first.Get<Document, byte[]>(x => x.Data);
+            var images = ImageUtils.RenderPDFToImages(data);
+            foreach (var image in images)
+            {
+                DocumentViewer.Children.Add(new Image
+                {
+                    Source = ImageUtils.LoadImage(image),
+                    Margin = new Thickness(0, 0, 0, 20)
+                });
+            }
+        }
+
+        private void ApproveButton_Click(object sender, RoutedEventArgs e)
         {
             bool bulkApprove = false;
             if (selectedSetouts.Count > 1)
@@ -139,9 +242,9 @@ public class Module
                 {
                     bulkApprove = true;
                     Progress.Show("Approving Setouts..");
-                }                  
+                }
             }
-            
+
             string message = "Result: " + Environment.NewLine;
 
             foreach (var item in selectedSetouts)
@@ -153,7 +256,7 @@ public class Module
                     message = message + returnstring + Environment.NewLine;
             }
 
-            if(bulkApprove)
+            if (bulkApprove)
                 Progress.Close();
 
             new Client<StagingSetout>().Save(selectedSetouts, "Updated from staging screen");
@@ -163,7 +266,7 @@ public class Module
             MessageBox.Show(message);
         }
 
-        private static string ApproveSetout(StagingSetout item, bool bulkapprove)
+        private string ApproveSetout(StagingSetout item, bool bulkapprove)
         {
             if (item.Group.ID == Guid.Empty)
             {
@@ -195,6 +298,7 @@ public class Module
                     new Columns<Setout>(x => x.ID))
                 .ToObjects<Setout>().FirstOrDefault();
 
+            string result;
             //setout already exists - create new setoutdoc and supercede old ones
             if (setout is not null)
             {
@@ -231,7 +335,7 @@ public class Module
                 new Client<SetoutDocument>().Save(setoutdocs, "Updated from Staging Screen");
                 new Client<Setout>().Save((Setout)setout, "Updated from Staging Screen");
 
-                return item.Number + " Superceded";
+                result = item.Number + " Superceded";
             }
             //no setout for this pdf - create new
             else
@@ -257,18 +361,65 @@ public class Module
                         return "";
                     }
                     else
-                        return item.Number + " Created";
+                        result = item.Number + " Created";
                 }
                 else
                 {
                     new Client<Setout>().Save(setout, "Added from staging screen");
                     CreateSetoutDocument(setout, item, setoutDocument);
-                    return item.Number + " Created";
+                    result = item.Number + " Created";
+                }
+            }
+
+            var packets = new List<Tuple<ManufacturingPacket, StagingManufacturingPacket>>();
+            foreach(var stagingPacket in ManufacturingPacketList.GetPackets())
+            {
+                if(stagingPacket.ManufacturingPacket.ID != Guid.Empty)
+                {
+                    MessageBox.Show($"A manufacturing packet already exists for {stagingPacket.Serial}; skipping packet.");
+                    continue;
                 }
+
+                var packet = new ManufacturingPacket
+                {
+                    Serial = stagingPacket.Serial,
+                    Title = stagingPacket.Title,
+                    Quantity = stagingPacket.Quantity,
+                    BarcodeQty = stagingPacket.BarcodeQuantity != 0 ? stagingPacket.BarcodeQuantity : stagingPacket.Quantity,
+                    WaterMark = stagingPacket.Watermark.ToString(),
+                    Location = stagingPacket.Location
+                };
+                packet.SetoutLink.ID = setout.ID;
+                packet.ITP.ID = stagingPacket.ITP.ID;
+                packet.JobLink.ID = stagingPacket.Job.ID;
+                packet.ManufacturingTemplateLink.ID = stagingPacket.Template.ID;
+
+                packets.Add(new(packet, stagingPacket));
             }
+            new Client<ManufacturingPacket>().Save(packets.Select(x => x.Item1), "Created from Design Management Panel");
+
+            var newStages = new List<ManufacturingPacketStage>();
+            foreach(var (packet, stagingPacket) in packets)
+            {
+                stagingPacket.ManufacturingPacket.ID = packet.ID;
+                var stages = new Client<StagingManufacturingPacketStage>()
+                    .Query(
+                        new Filter<StagingManufacturingPacketStage>(x => x.Packet.ID).IsEqualTo(stagingPacket.ID),
+                        IManufacturingPacketGeneratorExtensions.GetPacketGeneratorRequiredColumns<StagingManufacturingPacketStage>());
+                newStages.AddRange(stages.ToObjects<StagingManufacturingPacketStage>()
+                    .Select(x =>
+                    {
+                        var stage = x.CreateManufacturingPacketStage();
+                        stage.Parent.ID = packet.ID;
+                        return stage;
+                    }));
+            }
+            new Client<ManufacturingPacketStage>().Save(newStages, "Created from Design Management");
+            new Client<StagingManufacturingPacket>().Save(packets.Select(x => x.Item2), "Created from Design Management");
 
             //currently not creating packets due to temporary change in requirements - to uncomment and check for validity when required
             //CreatePackets(setout);
+            return result;
         }
 
         private static void CreateSetoutDocument(Setout setout, StagingSetout item, StagingSetoutDocument stagingsetoutdocument)
@@ -282,9 +433,9 @@ public class Module
             new Client<SetoutDocument>().Save(setoutdoc, "Added from staging screen");
         }
 
-        private void DocumentPreviewer_OnRejected(IEntityDocument? stagingsetoutdocument)
+        private void RejectButton_Click(object sender, RoutedEventArgs e)
         {
-            if(selectedSetout is null || stagingsetoutdocument is null)
+            if (selectedSetout is null || Document is null)
             {
                 MessageBox.Show("Please select a setout");
                 return;
@@ -307,7 +458,7 @@ public class Module
             {
                 var doc = new KanbanDocument();
                 doc.EntityLink.ID = task.ID;
-                doc.DocumentLink.ID = stagingsetoutdocument.DocumentLink.ID;
+                doc.DocumentLink.ID = Document.DocumentLink.ID;
                 new Client<KanbanDocument>().Save(doc, "Created from staging screen");
 
                 selectedSetout.Task.ID = task.ID;
@@ -316,7 +467,7 @@ public class Module
                 MessageBox.Show("Success - Task Created for Document " + selectedSetout.Number + " (Task no. " + task.Number + " assigned to " + task.EmployeeLink.Name + ")");
                 selectedSetout = null;
 
-                documentPreviewer.Document = null;
+                Document = null;
                 stagingSetoutGrid.Refresh(false, true);
             }
             else
@@ -325,14 +476,71 @@ public class Module
             }
         }
 
-        private void nestedPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
+        private void MarkUpButton_Click(object sender, RoutedEventArgs e)
         {
-            if(e.View != DynamicSplitPanelView.Master && ManufacturingPacketList.Setout != selectedSetout)
+            if (Mode == DocumentMode.Markup)
             {
-                ManufacturingPacketList.Setout = selectedSetout;
+                Mode = DocumentMode.Complete;
+                MessageBox.Show("IMPORTANT - press save in your document editor, then press the Complete Button in PRS");
+                OnMarkupSelected();
+            }
+            else
+            {
+                OnMarkupComplete();
+                Mode = DocumentMode.Markup;
+            }
+        }
+
+        private void OnMarkupSelected()
+        {
+            if (Document is null || selectedSetout is null)
+            {
+                MessageBox.Show("Please select a setout first.");
+                return;
+            }
+
+            var doc = new Client<Document>()
+                .Query(
+                    new Filter<Document>(x => x.ID).IsEqualTo(Document.DocumentLink.ID))
+                .ToObjects<Document>().FirstOrDefault();
+            if (doc is null)
+            {
+                Logger.Send(LogType.Error, "", $"Document with ID {Document.DocumentLink.ID} could not be found.");
+                MessageBox.Show("Error: the selected document could not be found in the database.");
+                return;
+            }
+
+            var tempdocpath = Path.Combine(Path.GetTempPath(), doc.FileName);
+            selectedSetout.SavePath = tempdocpath;
+            selectedSetout.Locked = DateTime.Now;
+            selectedSetout.LockedBy.ID = App.EmployeeID;
+            new Client<StagingSetout>().Save(selectedSetout, "Locked from Staging Screen");
+            File.WriteAllBytes(tempdocpath, doc.Data);
+            using (var p = new Process())
+            {
+                p.StartInfo = new ProcessStartInfo()
+                {
+                    UseShellExecute = true,
+                    FileName = tempdocpath
+                };
+
+                p.Start();
+            }
+            stagingSetoutGrid.Refresh(false, true);
+        }
+        private void OnMarkupComplete()
+        {
+            if (selectedSetout is null)
+            {
+                MessageBox.Show("Please select a setout first.");
+                return;
             }
+            StagingSetoutGrid.ReloadFile(selectedSetout);
+            stagingSetoutGrid.Refresh(false, true);
         }
 
+        #endregion
+
         private void StagingSetoutGrid_OnSelectItem(object sender, InABox.DynamicGrid.DynamicGridSelectionEventArgs e)
         {
             selectedSetouts.Clear();
@@ -344,7 +552,7 @@ public class Module
             AddPacketButton.IsEnabled = selectedSetout is not null;
             if(selectedSetout is null)
             {
-                documentPreviewer.Document = null;
+                Document = null;
                 ManufacturingPacketList.Setout = null;
                 CollapsePacketsButton.IsEnabled = false;
                 return;
@@ -358,22 +566,22 @@ public class Module
             if(doc is null)
             {
                 MessageBox.Show("No document found for this setout.");
-                documentPreviewer.Document = null;
+                Document = null;
                 return;
             }
 
-            documentPreviewer.Document = doc;
-            if(mainPanel.View != DynamicSplitPanelView.Master && nestedPanel.View != DynamicSplitPanelView.Master)
+            Document = doc;
+            if(MainPanel.View != DynamicSplitPanelView.Master && NestedPanel.View != DynamicSplitPanelView.Master)
             {
                 ManufacturingPacketList.Setout = selectedSetout;
             }
             CollapsePacketsButton.IsEnabled = true;
-            //manufacturingControl.StagingSetout = _item;
-            documentPreviewer.Mode =
-                selectedSetout.Locked == DateTime.MinValue ? InABox.Wpf.DocumentApprovalControl.ControlMode.Markup :
-                selectedSetout.Locked != DateTime.MinValue && selectedSetout.LockedBy.ID == App.EmployeeID ? InABox.Wpf.DocumentApprovalControl.ControlMode.Complete :
-                selectedSetout.Locked != DateTime.MinValue && selectedSetout.LockedBy.ID != App.EmployeeID ? InABox.Wpf.DocumentApprovalControl.ControlMode.Locked :
-               InABox.Wpf.DocumentApprovalControl.ControlMode.Markup;
+            Mode =
+                selectedSetout.Locked == DateTime.MinValue ?
+                    DocumentMode.Markup :
+                    selectedSetout.LockedBy.ID == App.EmployeeID ?
+                        DocumentMode.Complete :
+                        DocumentMode.Locked;
         }
 
         public bool IsReady { get; set; }
@@ -383,6 +591,8 @@ public class Module
 
         public event DataModelUpdateEvent? OnUpdateDataModel;
 
+        #region Settings
+
         public void CreateToolbarButtons(IPanelHost host)
         {
             host.CreateSetupAction(new PanelAction() { Caption = "Setouts Configuration", Image = PRSDesktop.Resources.specifications, OnExecute = ConfigSettingsClick });
@@ -437,6 +647,8 @@ public class Module
             }
         }
 
+        #endregion
+
         public void Heartbeat(TimeSpan time)
         {
 
@@ -446,11 +658,9 @@ public class Module
         {
             //stagingSetoutGrid.ScanFiles(_settings.SetoutsFolder);
             stagingSetoutGrid.Refresh(false, true);
-            documentPreviewer.Document = null;
+            Document = null;
 
             ManufacturingPacketList.Setout = null;
-            //manufacturingControl.StagingSetout = new StagingSetout();
-            //manufacturingControl.Refresh();
         }
 
         public Dictionary<string, object[]> Selected()
@@ -458,73 +668,6 @@ public class Module
             return new();
         }
 
-        public void Setup()
-        {
-            _settings = new GlobalConfiguration<StagingPanellSettings>().Load();
-
-            documentPreviewer.SetupButtons(
-                markupVisible: Security.IsAllowed<CanMarkUpSetouts>(),
-                rejectVisible: Security.IsAllowed<CanApproveSetouts>(),
-                approveVisible: Security.IsAllowed<CanApproveSetouts>()
-                );
-            documentPreviewer.OnMarkupSelected += DocumentPreviewer_OnMarkupSelected;
-            documentPreviewer.OnMarkupComplete += DocumentPreviewer_OnMarkupComplete;
-            documentPreviewer.OnRejected += DocumentPreviewer_OnRejected;
-            documentPreviewer.OnApproved += DocumentPreviewer_OnApproved;
-
-            //stagingSetoutGrid.ScanFiles(_settings.SetoutsFolder);
-            stagingSetoutGrid.Refresh(true, true);
-            stagingSetoutGrid.OnSelectItem += StagingSetoutGrid_OnSelectItem;
-        }
-
-
-        private void DocumentPreviewer_OnMarkupSelected(IEntityDocument? document)
-        {
-            if(document is null || selectedSetout is null)
-            {
-                MessageBox.Show("Please select a setout first.");
-                return;
-            }
-
-            var doc = new Client<Document>()
-                .Query(
-                    new Filter<Document>(x => x.ID).IsEqualTo(document.DocumentLink.ID))
-                .ToObjects<Document>().FirstOrDefault();
-            if (doc is null)
-            {
-                Logger.Send(LogType.Error, "", $"Document with ID {document.DocumentLink.ID} could not be found.");
-                MessageBox.Show("Error: the selected document could not be found in the database.");
-                return;
-            }
-
-            var tempdocpath = Path.GetTempPath() + @"\" + doc.FileName;
-            selectedSetout.SavePath = tempdocpath;
-            selectedSetout.LockedBy.ID = App.EmployeeID;
-            new Client<StagingSetout>().Save(selectedSetout, "Locked from Staging Screen");
-            File.WriteAllBytes(tempdocpath, doc.Data);
-            using (var p = new Process())
-            {
-                p.StartInfo = new ProcessStartInfo()
-                {
-                    UseShellExecute = true,
-                    FileName = tempdocpath
-                };
-
-                p.Start();
-            }
-            stagingSetoutGrid.Refresh(false, true);
-        }
-        private void DocumentPreviewer_OnMarkupComplete(IEntityDocument? document)
-        {
-            if (selectedSetout is null)
-            {
-                MessageBox.Show("Please select a setout first.");
-                return;
-            }
-            StagingSetoutGrid.ReloadFile(selectedSetout);
-            stagingSetoutGrid.Refresh(false, true);
-        }
-
 
         public void Shutdown(CancelEventArgs? cancel)
         {