Procházet zdrojové kódy

Refactoring Code to prepare for new Socket/Pipe based RPC Servers
Fixed Quote Module Startup bugs

Frank van den Bos před 2 roky
rodič
revize
bbf5ee682e

+ 1 - 1
prs.desktop/MainWindow.xaml

@@ -537,7 +537,7 @@
                     <fluent:Button x:Name="StockMovementList" Header="Stock Movements"
                                    LargeIcon="pack://application:,,,/Resources/forklift.png"
                                    Click="StockMovements_Checked" MinWidth="60" />                    
-                    <fluent:Button x:Name="StockSummaryButton" Header="Procurement Forecast"
+                    <fluent:Button x:Name="StockSummaryButton" Header="Stock Forecast"
                                    LargeIcon="pack://application:,,,/Resources/kpi.png"
                                    Click="StockSummaryButton_Clicked" MinWidth="60" />
                 </fluent:RibbonGroupBox>

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

@@ -156,20 +156,27 @@ namespace PRSDesktop
             switch (DatabaseType)
             {
                 case DatabaseType.Standalone:
-                    ClientFactory.SetClientType(typeof(LocalClient<>), Platform.Desktop, CoreUtils.GetVersion());
+                    ClientFactory.SetClientType(typeof(LocalClient<>), Platform.Wpf, CoreUtils.GetVersion());
                     DbFactory.ColorScheme = App.DatabaseSettings.ColorScheme;
                     DbFactory.Logo = App.DatabaseSettings.Logo;
                     break;
                 
                 case DatabaseType.Networked:
+                    
+                    //var url = App.DatabaseSettings.URLs.FirstOrDefault() ?? "localhost:8000";
+                    //ClientFactory.SetClientType(typeof(RPCClient<>), Platform.Wpf, CoreUtils.GetVersion(), () => new RPCClientSocketTransport(url));
+                    
                     var url = RestClient<User>.Ping(App.DatabaseSettings.URLs, out DatabaseInfo info);
-                    ClientFactory.SetClientType(typeof(RestClient<>), Platform.Desktop, CoreUtils.GetVersion(), 
+                    ClientFactory.SetClientType(typeof(RestClient<>), Platform.Wpf, CoreUtils.GetVersion(), 
                         url, true);
                     break;
                 
                 case DatabaseType.Local:
-                    ClientFactory.SetClientType(typeof(IPCClient<>), Platform.Desktop, CoreUtils.GetVersion(), 
-                        DatabaseServerProperties.GetPipeName(App.DatabaseSettings.LocalServerName));
+                    //var pipe = DatabaseServerProperties.GetPipeName(App.DatabaseSettings.LocalServerName);
+                    //ClientFactory.SetClientType(typeof(RPCClient<>), Platform.Wpf, CoreUtils.GetVersion(),
+                    //    () => new RPCClientPipeTransport(pipe));
+                     ClientFactory.SetClientType(typeof(IPCClient<>), Platform.Wpf, CoreUtils.GetVersion(), 
+                          DatabaseServerProperties.GetPipeName(App.DatabaseSettings.LocalServerName));
                     break;
             }
 

+ 1 - 10
prs.desktop/Panels/Quotes/QuoteDesignGrid.cs

@@ -7,22 +7,13 @@ namespace PRSDesktop
 {
     public class QuoteDesignGrid : DynamicDataGrid<QuoteDesign>
     {
-        private Guid _quoteid = Guid.Empty;
 
         public QuoteDesignGrid()
         {
             Options.AddRange(DynamicGridOption.RecordCount, DynamicGridOption.SelectColumns);
         }
 
-        public Guid QuoteID
-        {
-            get => _quoteid;
-            set
-            {
-                _quoteid = value;
-                Refresh(false, true);
-            }
-        }
+        public Guid QuoteID { get; set; }
 
         protected override void Reload(Filters<QuoteDesign> criteria, Columns<QuoteDesign> columns, ref SortOrder<QuoteDesign> sort,
             Action<CoreTable, Exception> action)

+ 76 - 24
prs.desktop/Panels/Quotes/QuoteDetails.xaml.cs

@@ -12,10 +12,10 @@ namespace PRSDesktop
     /// <summary>
     ///     Interaction logic for QuoteDetails.xaml
     /// </summary>
-    public partial class QuoteDetails : UserControl, IPanel<Quote>, IQuotePage
+    public partial class QuoteDetails : UserControl, IPanel<Quote>, IQuotePage, IDynamicEditorHost
     {
-        private CoreTable Data;
-
+        private CoreRow[] _rows;
+        
         public QuoteDetails()
         {
             InitializeComponent();
@@ -69,8 +69,7 @@ namespace PRSDesktop
 
         public Dictionary<string, object[]> Selected()
         {
-            var rows = Data != null ? Data.Rows.ToArray() : new CoreRow[] { };
-            return new Dictionary<string, object[]> { { typeof(Quote).EntityName(), rows } };
+            return new Dictionary<String, object[]>() { { typeof(Quote).EntityName(), _rows } };
         }
 
         public void Setup()
@@ -99,6 +98,7 @@ namespace PRSDesktop
             Customer.OtherColumns["Account.ID"] = "Account.ID";
             Customer.OtherColumns["Account.Code"] = "Account.Code";
             Customer.OtherColumns["Account.Name"] = "Account.Name";
+            Customer.Host = this;
             Customer.Configure();
             Customer.OnEditorValueChanged += Customer_OnEditorValueChanged;
             Customer.Loaded = true;
@@ -108,6 +108,7 @@ namespace PRSDesktop
             Account.CodeColumn = "Code";
             Account.OtherColumns["Code"] = "Account.Code";
             Account.OtherColumns["Name"] = "Account.Name";
+            Account.Host = this;
             Account.Configure();
             Account.OnEditorValueChanged += Account_OnEditorValueChanged;
             Account.Loaded = true;
@@ -126,28 +127,24 @@ namespace PRSDesktop
 
         private void UpdateScreen(CoreTable o, Exception e)
         {
-            Data = o;
+            _rows = o?.Rows.ToArray() ?? new CoreRow[] { };
             Dispatcher.Invoke(() =>
             {
                 var bIsReady = IsReady;
                 IsReady = false;
 
-                Title.Value = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, string>(col => col.Title) : "";
-                Customer.Value = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, Guid>(col => col.Customer.ID) : Guid.Empty;
-                //CustomerCode.Text = (o != null) && o.Rows.Any() ? o.Rows.First().Get<Quote, String>(col => col.Customer.Code) : "";
-                //CustomerName.Text = (o != null) && o.Rows.Any() ? o.Rows.First().Get<Quote, String>(col => col.Customer.Name) : "";
-                Address.Text = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, string>(col => col.SiteAddress.Street) : "";
-                City.Text = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, string>(col => col.SiteAddress.City) : "";
-                State.Text = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, string>(col => col.SiteAddress.State) : "";
-                PostCode.Text = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, string>(col => col.SiteAddress.PostCode) : "";
-                Account.Value = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, Guid>(col => col.Account.ID) : Guid.Empty;
-                //AccountCode.Text = (o != null) && o.Rows.Any() ? o.Rows.First().Get<Quote, String>(col => col.Account.Code) : "";
-                //AccountName.Text = (o != null) && o.Rows.Any() ? o.Rows.First().Get<Quote, String>(col => col.Account.Name) : "";
-
-                var notes = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, string[]>(col => col.Notes) : null;
+                Title.Value = o?.Rows.FirstOrDefault()?.Get<Quote, string>(col => col.Title) ?? "";
+                Customer.Value = o?.Rows.FirstOrDefault()?.Get<Quote, Guid>(col => col.Customer.ID) ?? Guid.Empty;
+                Address.Text = o?.Rows.FirstOrDefault()?.Get<Quote, string>(col => col.SiteAddress.Street) ?? "";
+                City.Text = o?.Rows.FirstOrDefault()?.Get<Quote, string>(col => col.SiteAddress.City) ?? "";
+                State.Text = o?.Rows.FirstOrDefault()?.Get<Quote, string>(col => col.SiteAddress.State) ?? "";
+                PostCode.Text = o?.Rows.FirstOrDefault()?.Get<Quote, string>(col => col.SiteAddress.PostCode) ?? "";
+                Account.Value = o?.Rows.FirstOrDefault()?.Get<Quote, Guid>(col => col.Account.ID) ?? Guid.Empty;
+
+                var notes = o?.Rows.FirstOrDefault()?.Get<Quote, string[]>(col => col.Notes) ?? null;
                 Notes.Text = notes != null ? string.Join("\n\n", notes).Replace("\r\n\r\n", "\r\n").Replace("\n\n", "\n") : "";
 
-                Status.SelectedValue = o != null && o.Rows.Any() ? o.Rows.First().Get<Quote, Guid>(col => col.Status.ID) : Guid.Empty;
+                Status.SelectedValue = o?.Rows.FirstOrDefault()?.Get<Quote, Guid>(col => col.Status.ID) ?? Guid.Empty;
 
                 QuoteValue.Text = o != null && o.Rows.Any() ? string.Format("${0:F2}", o.Rows.First().Get<Quote, double>(col => col.ExTax)) : "";
 
@@ -160,7 +157,7 @@ namespace PRSDesktop
             if (IsReady)
             {
                 var quote = new Quote { ID = ParentID };
-                quote.Number = Data != null && Data.Rows.Any() ? Data.Rows.First().Get<Quote, string>(col => col.Number) : "";
+                quote.Number = _rows?.FirstOrDefault()?.Get<Quote, string>(col => col.Number) ?? "";
                 quote.Title = Title.Value;
                 new Client<Quote>().Save(quote, "Updated Title", (j, err) => { });
             }
@@ -172,7 +169,7 @@ namespace PRSDesktop
             if (IsReady)
             {
                 var quote = new Quote { ID = ParentID };
-                quote.Number = Data != null && Data.Rows.Any() ? Data.Rows.First().Get<Quote, string>(col => col.Number) : "";
+                quote.Number = _rows.FirstOrDefault()?.Get<Quote, string>(col => col.Number) ?? "";
                 quote.Customer.ID = (Guid)values["Customer.ID"];
                 quote.Account.ID = (Guid)values["Account.ID"];
                 new Client<Quote>().Save(quote, "Updated Customer ID", (j, err) => { });
@@ -184,7 +181,7 @@ namespace PRSDesktop
             if (IsReady)
             {
                 var quote = new Quote { ID = ParentID };
-                quote.Number = Data != null && Data.Rows.Any() ? Data.Rows.First().Get<Quote, string>(col => col.Number) : "";
+                quote.Number = _rows?.FirstOrDefault()?.Get<Quote, string>(col => col.Number) ?? "";
                 quote.Account.ID = (Guid)values["Account.ID"];
                 new Client<Quote>().Save(quote, "Updated Account ID", (j, err) => { });
             }
@@ -195,10 +192,65 @@ namespace PRSDesktop
             if (IsReady)
             {
                 var quote = new Quote { ID = ParentID };
-                quote.Number = Data != null && Data.Rows.Any() ? Data.Rows.First().Get<Quote, string>(col => col.Number) : "";
+                quote.Number = _rows?.FirstOrDefault()?.Get<Quote, string>(col => col.Number) ?? "";
                 quote.Status.ID = Status.SelectedValue != null ? (Guid)Status.SelectedValue : Guid.Empty;
                 new Client<Quote>().Save(quote, "Updated Quote Status", (j, err) => { });
             }
         }
+        
+        #region IDynamicEditorHost
+
+        public IEnumerable<DynamicGridColumn> Columns { get; } = InitialiseColumns();
+
+        private static DynamicGridColumns InitialiseColumns()
+        {
+            var columns = new DynamicGridColumns();
+            columns.ExtractColumns(typeof(Quote));
+            return columns;
+        }
+
+        public void LoadColumns(string column, Dictionary<string, string> columns)
+        {
+            columns.Clear();
+            var comps = column.Split('.').ToList();
+            comps.RemoveAt(comps.Count - 1);
+            var prefix = string.Format("{0}.", string.Join(".", comps));
+            var cols = Columns.Where(x => !x.ColumnName.Equals(column) && x.ColumnName.StartsWith(prefix));
+            foreach (var col in cols)
+                columns[col.ColumnName.Replace(prefix, "")] = col.ColumnName;
+        }
+
+        public IFilter? DefineFilter(Type type) => LookupFactory.DefineFilter<Quote>(new Quote[] { new Quote() }, type);
+
+        public void LoadLookups(ILookupEditorControl editor)
+        {
+            //if (editor == Activity) Activity_OnDefineLookups(editor);
+            //else if (editor == Kanban) Task_OnDefineLookups(editor);
+            //else if (editor == ITP) ITP_OnDefineLookups(editor);
+        }
+
+        public Document? FindDocument(string filename)
+        {
+            return new Client<Document>().Load(new Filter<Document>(x => x.FileName).IsEqualTo(filename)).FirstOrDefault();
+        }
+
+        public Document? GetDocument(Guid id)
+        {
+            Document? doc = null;
+            if (id != Guid.Empty)
+                doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(id)).FirstOrDefault();
+            return doc;
+        }
+
+        public void SaveDocument(Document document)
+        {
+            new Client<Document>().Save(document, "");
+        }
+
+        object?[] IDynamicEditorHost.GetItems() => new object?[] { new Quote() };
+
+        public BaseEditor? GetEditor(DynamicGridColumn column) => column.Editor.CloneEditor();
+        
+        #endregion
     }
 }

+ 6 - 12
prs.desktop/Panels/Quotes/QuoteTakeoffs.cs

@@ -8,8 +8,9 @@ namespace PRSDesktop
 {
     public class QuoteTakeoffs : DynamicDataGrid<QuoteTakeoff>, IQuotePage, IDataModelSource
     {
-        private Guid _quoteid = Guid.Empty;
-
+        
+        public Guid ParentID { get; set; }
+        
         public QuoteTakeoffs()
         {
             Options.AddRange(
@@ -31,16 +32,7 @@ namespace PRSDesktop
             var ids = ExtractValues(x => x.ID, selection).ToArray();
             return new BaseDataModel<QuoteTakeoff>(new Filter<QuoteTakeoff>(x => x.ID).InList(ids));
         }
-
-        public Guid ParentID
-        {
-            get => _quoteid;
-            set
-            {
-                _quoteid = value;
-                Refresh(false, true);
-            }
-        }
+        
 
         protected override void Reload(Filters<QuoteTakeoff> criteria, Columns<QuoteTakeoff> columns, ref SortOrder<QuoteTakeoff> sort,
             Action<CoreTable, Exception> action)
@@ -55,5 +47,7 @@ namespace PRSDesktop
             result.Quote.ID = ParentID;
             return result;
         }
+
+
     }
 }

+ 1 - 0
prs.server/Engines/Certificate/CertHelper.cs

@@ -21,6 +21,7 @@ using Org.BouncyCastle.X509;
 using Attribute = Org.BouncyCastle.Asn1.Cms.Attribute;
 using SysHashAlgorName = System.Security.Cryptography.HashAlgorithmName;
 using BcCertificate = Org.BouncyCastle.X509.X509Certificate;
+using BigInteger = Org.BouncyCastle.Math.BigInteger;
 using X509Extension = Org.BouncyCastle.Asn1.X509.X509Extension;
 
 namespace PRSServer

+ 14 - 3
prs.server/Engines/Database/DatabaseEngine.cs

@@ -26,6 +26,9 @@ namespace PRSServer
         private string PipeName;
         private IPCServer? PipeServer;
 
+        //private IRPCServer? _pipeserver;
+        //private IRPCServer? _socketserver;
+        
         public override void Configure(Server server)
         {
             base.Configure(server);
@@ -199,18 +202,24 @@ namespace PRSServer
             CredentialsCache.SetSessionExpiryTime(TimeSpan.FromMinutes(Properties.SessionExpiryTime));
 
             Logger.Send(LogType.Information, "", string.Format("Starting Rest Listener: Port={0}", Properties.Port));
-            if(Properties.WebSocketPort != 0)
+            if (Properties.WebSocketPort != 0)
             {
                 Logger.Send(LogType.Information, "", string.Format("Starting Web Socket Listener: Port={0}", Properties.WebSocketPort));
+                RestListener.Init(Properties.WebSocketPort);
             }
 
-            RestListener.Init(Properties.WebSocketPort);
             InitialisePort();
             RestListener.Start();
-
+            // _socketserver = new RPCServer<RPCServerSocketTransport>(() => new RPCServerSocketTransport(Properties.Port));
+            // _socketserver.OnLog += (type, userid, message) => Logger.Send(type, userid, $"[S] {message}");
+            // _socketserver.Start();
             Logger.Send(LogType.Information, "", string.Format("Rest Server Started listening on port {0}", Properties.Port));
+            
 
             Logger.Send(LogType.Information, "", $"Starting Pipe Listener with pipe name {PipeName}");
+            // _pipeserver = new RPCServer<RPCServerPipeTransport>(() => new RPCServerPipeTransport(PipeName));
+            // _pipeserver.OnLog += (type, userid, message) => Logger.Send(type, userid, $"[P] {message}");
+            // _pipeserver.Start();
             PipeServer = new IPCServer(PipeName);
             PipeServer.Start();
 
@@ -400,6 +409,8 @@ namespace PRSServer
         {
             Logger.Send(LogType.Information, "", "Stopping..");
 
+            //_pipeserver?.Stop();
+            //_pipeserver = null;
             PipeServer?.Dispose();
 
             RestListener.Stop();

+ 5 - 4
prs.server/Engines/Engine.cs

@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 using System.Reflection;
+using InABox.Core;
 using InABox.IPC;
 using InABox.Logging;
 
@@ -22,7 +23,7 @@ namespace PRSServer
     public abstract class Engine<TProperties> : IEngine where TProperties : ServerProperties
     {
         
-        private RPCServerTransport _enginemanager;
+        private RPCServerPipeTransport _enginemanager;
 
         public TProperties Properties { get; private set; }
         public abstract void Run();
@@ -47,9 +48,9 @@ namespace PRSServer
             MainLogger.AddLogger(new LogFileLogger(AppDataFolder));
             MainLogger.AddLogger(new NamedPipeLogger(server.Key));
             
-            _enginemanager = new RPCServerTransport($"{ServiceName}$");
-            _enginemanager.AddCommandHandler<IEngine, PortStatusCommand, PortStatusParameters, PortStatus[]>(new PortStatusHandler(this));
-            _enginemanager.OnLog += MainLogger.Send;
+            _enginemanager = new RPCServerPipeTransport($"{ServiceName}$");
+            _enginemanager.AddHandler<IEngine, PortStatusCommand, PortStatusParameters, PortStatus[]>(new PortStatusHandler(this));
+            _enginemanager.AfterMessage += (transport, args) => MainLogger.Send(LogType.Information,"",$"Engine Manager Message: {args.Message?.Command}");
             _enginemanager.Start();
         }
 

+ 1 - 1
prs.server/Engines/PortStatus.cs

@@ -51,7 +51,7 @@ namespace PRSServer
     
     public class PortStatusHandler : RPCCommandHandler<IEngine,PortStatusParameters,PortStatus[]> 
     {
-        public override PortStatus[]? Execute(IEngine sender, PortStatusParameters? parameters) => sender.PortStatusList();
+        public override PortStatus[]? Execute(PortStatusParameters? parameters) => Sender.PortStatusList();
 
         public PortStatusHandler(IEngine sender) : base(sender)
         {

+ 0 - 14
prs.server/Forms/DatabaseLicense/LicenseRenewalForm.xaml.cs

@@ -1,33 +1,19 @@
 using System;
 using System.Collections.Generic;
-using System.IO.Compression;
-using System.IO;
 using System.Linq;
-using System.Security.Policy;
-using System.Threading;
 using System.Windows;
 using InABox.Clients;
 using InABox.Core;
 using InABox.DynamicGrid;
 using InABox.Wpf;
 using InABox.WPF;
-using Microsoft.Exchange.WebServices.Data;
-using PRSServer.Forms.DatabaseLicense;
-using RestSharp;
 using Stripe;
-using DataFormat = RestSharp.DataFormat;
-using System.Net;
-using FastReport.DevComponents.DotNetBar;
 using System.Diagnostics.CodeAnalysis;
-using InABox.Database;
-using System.Runtime.CompilerServices;
 using System.Windows.Controls;
 using System.Drawing;
 using Image = System.Windows.Controls.Image;
 using System.Diagnostics;
-using Twilio.Rest.Api.V2010.Account;
 using InABox.Configuration;
-using RazorEngine.Compilation.ImpromptuInterface;
 
 namespace PRSServer.Forms.DatabaseLicense
 {

+ 3 - 3
prs.server/Forms/ServiceStatus.xaml.cs

@@ -63,7 +63,7 @@ namespace PRSServer
     public partial class ServiceStatus : Window
     {
 
-        private List<RPCClientTransport> _pipes = new List<RPCClientTransport>();
+        private List<RPCClientPipeTransport> _pipes = new List<RPCClientPipeTransport>();
         
         private String[] _domains;
         private Server[] _servers;
@@ -121,8 +121,8 @@ namespace PRSServer
         {
             foreach (var server in servers)
             {
-                var manager = new RPCClientTransport($"{server.Key}$");
-                manager.OnConnect += () => Task.Run(() =>
+                var manager = new RPCClientPipeTransport($"{server.Key}$");
+                manager.OnOpen += (o,e) => Task.Run(() =>
                 {
                     Dispatcher.Invoke(() => { Messages.Items.Add("Connected to Server"); });
                     //while (!manager.Disconnected)

+ 2 - 0
prs.server/PRSServer.csproj

@@ -87,6 +87,7 @@
         <ProjectReference Include="..\..\InABox\InABox.Client.IPC\InABox.Client.IPC.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.Client.Local\InABox.Client.Local.csproj" />
         <ProjectReference Include="..\..\inabox\inabox.client.rest\InABox.Client.Rest\InABox.Client.Rest.csproj" />
+        <ProjectReference Include="..\..\inabox\InABox.Client.RPC\InABox.Client.RPC.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.Configuration\InABox.Configuration.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.Core\InABox.Core.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.Database.SQLite\InABox.Database.SQLite.csproj" />
@@ -98,6 +99,7 @@
         <ProjectReference Include="..\..\InABox\InABox.Mailer.Exchange\InABox.Mailer.Exchange.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.Scripting\InABox.Scripting.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.Server\InABox.Server.csproj" />
+        <ProjectReference Include="..\..\inabox\InABox.SMSProviders\InABox.SMSProviders.csproj" />
         <ProjectReference Include="..\..\InABox\InABox.WPF\InABox.Wpf.csproj" />
         <ProjectReference Include="..\PRS.Classes\PRSClasses.csproj" />
         <ProjectReference Include="..\PRS.Shared\PRS.Shared.csproj" />

+ 3 - 3
prs.stores/BaseStore.cs

@@ -63,14 +63,14 @@ namespace Comal.Stores
             {
                 platform.Version = Version;
 
-                if(Platform == Platform.Desktop || Platform == Platform.Mobile)
+                if(Platform == Platform.Wpf || Platform == Platform.Mobile)
                 {
                     var user = Provider.Load(new Filter<User>(x => x.UserID).IsEqualTo(UserID)).FirstOrDefault();
                     if(user is not null)
                     {
                         var current = Platform switch
                         {
-                            Platform.Desktop => user.Platform.DesktopVersion,
+                            Platform.Wpf => user.Platform.DesktopVersion,
                             Platform.Mobile => user.Platform.MobileVersion,
                             _ => ""
                         };
@@ -78,7 +78,7 @@ namespace Comal.Stores
                         {
                             switch (Platform)
                             {
-                                case Platform.Desktop:
+                                case Platform.Wpf:
                                     user.Platform.DesktopVersion = Version;
                                     break;
                                 case Platform.Mobile: