Added logging + array based processing.

This commit is contained in:
Patrick Fic
2020-06-01 13:39:33 -07:00
parent db86d0bc55
commit 5c3160321b
8 changed files with 215 additions and 181 deletions

View File

@@ -327,6 +327,7 @@
<Compile Include="Models\DTO_Base.cs" /> <Compile Include="Models\DTO_Base.cs" />
<Compile Include="Models\DTO_QueueItem.cs" /> <Compile Include="Models\DTO_QueueItem.cs" />
<Compile Include="Models\Monitor.cs" /> <Compile Include="Models\Monitor.cs" />
<Compile Include="Models\QbXmlResponse.cs" />
<Compile Include="Properties\Resources.es-MX.Designer.cs"> <Compile Include="Properties\Resources.es-MX.Designer.cs">
<DependentUpon>Resources.es-MX.resx</DependentUpon> <DependentUpon>Resources.es-MX.resx</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace BodyshopPartner.Models
{
public class QbXmlResponse : DTO_Base
{
public QbXmlResponse()
{
}
private string _statusCode;
public string StatusCode
{
get { return _statusCode; }
set { SetProperty(ref _statusCode, value); }
}
private string _statusSeverity;
public string StatusSeverity
{
get { return _statusSeverity; }
set { SetProperty(ref _statusSeverity, value); }
}
private string _statusMessage;
public string StatusMessage
{
get { return _statusMessage; }
set { SetProperty(ref _statusMessage, value); }
}
private string _responseType;
public string ResponseType
{
get { return _responseType; }
set { SetProperty(ref _responseType, value); }
}
private XDocument _response;
public XDocument Response
{
get { return _response; }
set { SetProperty(ref _response, value); }
}
public override string ToString()
{
string r = $"Response Type: {ResponseType} | Severity: {StatusSeverity} | Code: {StatusCode} | {StatusMessage}";
return r;
}
}
}

View File

@@ -18,7 +18,7 @@ namespace BodyshopPartner.Utils
public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
logger.Fatal((e.ExceptionObject as Exception), "Unhandled generic exception."); logger.Fatal((e.ExceptionObject as Exception), "Unhandled generic exception. ");
} }
} }
} }

View File

@@ -5,14 +5,18 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using SimpleHttp; using SimpleHttp;
using System.Xml.Linq; using System.Xml.Linq;
using Newtonsoft;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BodyshopPartner.Utils namespace BodyshopPartner.Utils
{ {
public static class HTTPServer public static class HTTPServer
{ {
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
public delegate void HttpLogger(string s);
public static void InitHttpServer() private static HttpLogger hlog;
public static void InitHttpServer(HttpLogger HttpLogger)
{ {
Route.Add("/qb/receivables", (req, res, props) => Route.Add("/qb/receivables", (req, res, props) =>
{ {
@@ -26,7 +30,8 @@ namespace BodyshopPartner.Utils
, "POST"); , "POST");
logger.Trace("Starting HTTP server..."); logger.Trace("Starting HTTP server...");
hlog = HttpLogger;
hlog("Starting HTTP server...");
//TODO As a part of the installer, add netsh http add urlacl url=http://+:1337/ user="Everyone //TODO As a part of the installer, add netsh http add urlacl url=http://+:1337/ user="Everyone
HttpServer.ListenAsync(1337, System.Threading.CancellationToken.None, Route.OnHttpRequestAsync).Wait(); HttpServer.ListenAsync(1337, System.Threading.CancellationToken.None, Route.OnHttpRequestAsync).Wait();
} }
@@ -34,28 +39,44 @@ namespace BodyshopPartner.Utils
private static void HandleQbReceivables(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res) private static void HandleQbReceivables(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res)
{ {
logger.Debug("/qb/receivables - POST"); logger.Debug("/qb/receivables - POST");
//Input will be an array of XMLs.
string requestXMLstring = ParseBodyToString(req); string[] requestXMLstrings = ParseBodyToArray(req);
XDocument requestXMLdoc = ParseStringToXml(requestXMLstring); hlog("Received QuickBooks Receivable request.");
string CustomerId = QuickBooksInterop.CreateCustomerIfNotExist(requestXMLdoc); // string requestXMLstring = ParseBodyToString(req);
foreach (var requestXMLstring in requestXMLstrings)
string InvoiceAddResponse = QuickBooksInterop.ProcessQBXmlRequest(requestXMLstring);
string[] status = new string[3];
if (InvoiceAddResponse != null) status = QuickBooksInterop.parseInvoiceAddRs(InvoiceAddResponse);
if (InvoiceAddResponse != null && status[0] == "0")
{ {
logger.Debug("Invoice added successfully."); XDocument requestXMLdoc = ParseStringToXml(requestXMLstring);
XDocument response = XDocument.Parse(QuickBooksInterop.ProcessQBXmlRequest(requestXMLstring));
Models.QbXmlResponse ResponseStatus = QuickBooksInterop.ParseResponseXml(response);
logger.Info(response.ToString());
logger.Info(ResponseStatus.ToString());
hlog(ResponseStatus.ToString());
//string[] status = new string[3];
//if (InvoiceAddResponse != null) status = QuickBooksInterop.parseInvoiceAddRs(InvoiceAddResponse);
//if (InvoiceAddResponse != null && status[0] == "0")
//{ logger.Debug("Invoice added successfully."); res.StatusCode = 200; }
//else
//{ logger.Error("Error adding Invoice.\nStatus Code: {0} \nSeverity: {1} \nMessage {2}", status[0], status[1], status[2]); res.StatusCode = 400; }
} }
else hlog("Completed QuickBooks Receivable request.");
{ res.WithCORS().Close();
logger.Error("Error adding Invoice.\nStatus Code: {0} \nSeverity: {1} \nMessage {2}", status[0], status[1], status[2]); }
}
res.WithCORS().AsText("Hello."); public static string[] ParseBodyToArray(System.Net.HttpListenerRequest req)
{
System.IO.Stream body = req.InputStream;
System.Text.Encoding encoding = req.ContentEncoding;
System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
string s = reader.ReadToEnd();
body.Close();
reader.Close();
return JArray.Parse(s).Select(jv => jv.ToString()).ToArray();
} }
public static string ParseBodyToString(System.Net.HttpListenerRequest req) public static string ParseBodyToString(System.Net.HttpListenerRequest req)
@@ -63,17 +84,7 @@ namespace BodyshopPartner.Utils
System.IO.Stream body = req.InputStream; System.IO.Stream body = req.InputStream;
System.Text.Encoding encoding = req.ContentEncoding; System.Text.Encoding encoding = req.ContentEncoding;
System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding); System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
//if (req.ContentType != null)
//{
// Console.WriteLine("Client data content type {0}", req.ContentType);
//}
//Console.WriteLine("Client data content length {0}", req.ContentLength64);
//Console.WriteLine("Start of client data:");
// Convert the data to a string and display it on the console.
string s = reader.ReadToEnd(); string s = reader.ReadToEnd();
//Console.WriteLine(s);
//Console.WriteLine("End of client data:");
body.Close(); body.Close();
return s; return s;
} }

View File

@@ -71,113 +71,49 @@ namespace BodyshopPartner.Utils
} }
} }
public static string[] parseInvoiceAddRs(string xml) public static Models.QbXmlResponse ParseResponseXml(XDocument response)
{ {
string[] retVal = new string[3]; XElement QueryResponse = response.Root.Descendants("QBXMLMsgsRs").Descendants().FirstOrDefault();
try XAttribute StatusCode = QueryResponse.Attribute("statusCode");
XAttribute StatusSeverity = QueryResponse.Attribute("statusSeverity");
XAttribute statusMessage = QueryResponse.Attribute("statusMessage");
return new Models.QbXmlResponse()
{ {
XmlNodeList RsNodeList = null; StatusCode = System.Text.RegularExpressions.Regex.Unescape(StatusCode.Value),
XmlDocument Doc = new XmlDocument(); StatusMessage = System.Text.RegularExpressions.Regex.Unescape(statusMessage.Value),
Doc.LoadXml(xml); StatusSeverity = System.Text.RegularExpressions.Regex.Unescape(StatusSeverity.Value),
RsNodeList = Doc.GetElementsByTagName("InvoiceAddRs"); ResponseType = System.Text.RegularExpressions.Regex.Unescape(QueryResponse.Name.LocalName),
XmlAttributeCollection rsAttributes = RsNodeList.Item(0).Attributes; Response = response
XmlNode statusCode = rsAttributes.GetNamedItem("statusCode"); };
retVal[0] = Convert.ToString(statusCode.Value); //response.
XmlNode statusSeverity = rsAttributes.GetNamedItem("statusSeverity");
retVal[1] = Convert.ToString(statusSeverity.Value);
XmlNode statusMessage = rsAttributes.GetNamedItem("statusMessage");
retVal[2] = Convert.ToString(statusMessage.Value);
}
catch (Exception e)
{
logger.Error("Error encountered when parsing Invoice info returned from QuickBooks: " + e.Message);
retVal = null;
}
return retVal;
} }
public static string CreateCustomerIfNotExist(XDocument requestXML) //public static string[] parseInvoiceAddRs(string xml)
{ //{
string ListID = ParseCustomerId(requestXML); // string[] retVal = new string[3];
if (string.IsNullOrEmpty(ListID)) // try
//Could be null or exist, we need to check. // {
{ // XmlNodeList RsNodeList = null;
QBSessionManager sessionManager = new QBSessionManager(); // XmlDocument Doc = new XmlDocument();
IMsgSetRequest requestMsgSet = sessionManager.CreateMsgSetRequest("CA", 13, 0); // Doc.LoadXml(xml);
requestMsgSet.Attributes.OnError = ENRqOnError.roeContinue; // RsNodeList = Doc.GetElementsByTagName("InvoiceAddRs");
// XmlAttributeCollection rsAttributes = RsNodeList.Item(0).Attributes;
// XmlNode statusCode = rsAttributes.GetNamedItem("statusCode");
// retVal[0] = Convert.ToString(statusCode.Value);
// XmlNode statusSeverity = rsAttributes.GetNamedItem("statusSeverity");
// retVal[1] = Convert.ToString(statusSeverity.Value);
// XmlNode statusMessage = rsAttributes.GetNamedItem("statusMessage");
// retVal[2] = Convert.ToString(statusMessage.Value);
// }
// catch (Exception e)
// {
// logger.Error("Error encountered when parsing Invoice info returned from QuickBooks: " + e.Message);
// retVal = null;
// }
// return retVal;
//}
ICustomerAdd CustomerAddRq = requestMsgSet.AppendCustomerAddRq();
//Get the address & Other information from the request XML DOC.
CustomerAddRq.Name.SetValue(requestXML.Descendants("CustomerRef").First()?.Element("FullName")?.Value);
// ICustomerQuery CustomerQueryRq = requestMsgSet.AppendCustomerQueryRq();
//CustomerQueryRq.ORCustomerListQuery.ListIDList.Add(ListID);
string ret = ProcessQBXmlRequest(requestMsgSet.ToXMLString());
return ret;
}
else
{
return ListID;
}
}
public static string[] parseCustomerQueryRs(string xml)
{
string[] retVal;
try
{
XDocument responseXml = XDocument.Parse(xml);
XElement CustomerQueryRs = responseXml.Descendants("CustomerQueryRs").First();
XAttribute statusCode = CustomerQueryRs.Attribute(XName.Get("statusCode"));
if (statusCode.Value?.ToString() == "0")
{
//All good, return the ID.
}
else
{
//Need to create a new customer and return that ID.
}
//XmlNodeList RsNodeList = null;
//XmlDocument Doc = new XmlDocument();
//Doc.LoadXml(xml);
//RsNodeList = Doc.GetElementsByTagName("CustomerQueryRs");
//XmlAttributeCollection rsAttributes = RsNodeList.Item(0).Attributes;
//XmlNode statusCode = rsAttributes.GetNamedItem("statusCode");
//if (Convert.ToString(statusCode.Value) == "0")
//{
// //Found an ID for this person. Looks all good.
// retVal = new string[1];
// //xml.Desce
//}
//else
//{
// retVal = new string[3];
// retVal[0] = Convert.ToString(statusCode.Value);
// XmlNode statusSeverity = rsAttributes.GetNamedItem("statusSeverity");
// retVal[1] = Convert.ToString(statusSeverity.Value);
// XmlNode statusMessage = rsAttributes.GetNamedItem("statusMessage");
// retVal[2] = Convert.ToString(statusMessage.Value);
//}
//;
}
catch (Exception e)
{
logger.Error("Error encountered when parsing Invoice info returned from QuickBooks: " + e.Message);
retVal = null;
}
return retVal;
}
private static string ParseCustomerId(XDocument xml)
{
XElement CustomerRef = xml.Descendants("CustomerRef").First();
string ListId = CustomerRef.Element("ListID")?.Value;
return ListId;
}
} }
} }

View File

@@ -76,7 +76,7 @@ namespace BodyshopPartner.ViewModels
_callingThread.ReportProgress(80); _callingThread.ReportProgress(80);
Utils.HTTPServer.InitHttpServer(); Utils.HTTPServer.InitHttpServer(AddHttpStatus);
logger.Debug("VM Init Complete"); logger.Debug("VM Init Complete");
_callingThread.ReportProgress(100); _callingThread.ReportProgress(100);
@@ -215,22 +215,29 @@ namespace BodyshopPartner.ViewModels
IndeterminateLoading = false; IndeterminateLoading = false;
} }
public void AddHttpStatus(string s)
{
string newLine = $"\n{DateTime.Now.ToString("MM/dd/yy hh:mm:ss tt")}: {s}";
HttpServerLog += newLine;
logger.Trace(newLine);
}
private FirebaseAuthLink al = BodyshopPartner.Utils.Auth.authlink; private FirebaseAuthLink al = BodyshopPartner.Utils.Auth.authlink;
public async Task TestGql() public async Task TestGql()
{ {
//Notification _n = new Notification() Notification _n = new Notification()
//{ {
// Id = 123, Id = 123,
// Title = "This is a title", Title = "This is a title",
// Subtitle = "Subtitle", Subtitle = "Subtitle",
// Message = "Somethin" Message = "Somethin"
//}; };
//Growler.AddNotification(_n); Growler.AddNotification(_n);
Console.WriteLine(al.FirebaseToken); Console.WriteLine(al.FirebaseToken);
FirebaseAuthLink t = await al.GetFreshAuthAsync(); FirebaseAuthLink t = await al.GetFreshAuthAsync();
Console.WriteLine(t.FirebaseToken); Console.WriteLine(t.FirebaseToken);
AddHttpStatus(t.FirebaseToken);
//var r = new GraphQLRequest //var r = new GraphQLRequest
//{ //{
// Query = @"query MyQuery($key: String!) { // Query = @"query MyQuery($key: String!) {

View File

@@ -48,5 +48,12 @@ namespace BodyshopPartner.ViewModels
get { return _activeShop; } get { return _activeShop; }
set { SetProperty(ref _activeShop, value); Task.Run(async () => await SetActiveBodyshop()); } set { SetProperty(ref _activeShop, value); Task.Run(async () => await SetActiveBodyshop()); }
} }
private string _httpServerLog = "Status Log\nNewLine\n";
public string HttpServerLog
{
get { return _httpServerLog; }
set { SetProperty(ref _httpServerLog, value); }
}
} }
} }

View File

@@ -141,21 +141,26 @@
Content="_TEST" /> Content="_TEST" />
</StackPanel> </StackPanel>
<Grid>
<DataGrid ItemsSource="{Binding MonitoringPaths}" <Grid.ColumnDefinitions>
AutoGenerateColumns="False" <ColumnDefinition Width="*" />
VerticalContentAlignment="Center" <ColumnDefinition Width="*" />
IsReadOnly="True" </Grid.ColumnDefinitions>
HorizontalContentAlignment="Center" <DataGrid Grid.Column="0"
Margin="8" ItemsSource="{Binding MonitoringPaths}"
CanUserAddRows="False" AutoGenerateColumns="False"
CanUserSortColumns="True" VerticalContentAlignment="Center"
materialDesign:DataGridAssist.CellPadding="4 2 2 2" IsReadOnly="True"
materialDesign:DataGridAssist.ColumnHeaderPadding="4 2 2 2"> HorizontalContentAlignment="Center"
<DataGrid.Columns> Margin="8"
<DataGridTextColumn Binding="{Binding FilePath}" CanUserAddRows="False"
Header="{x:Static p:Resources.Label_FilePath}" /> CanUserSortColumns="True"
<!--<DataGridTextColumn Binding="{Binding Source}" materialDesign:DataGridAssist.CellPadding="4 2 2 2"
materialDesign:DataGridAssist.ColumnHeaderPadding="4 2 2 2">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding FilePath}"
Header="{x:Static p:Resources.Label_FilePath}" />
<!--<DataGridTextColumn Binding="{Binding Source}"
Header="{x:Static p:Resources.Label_SourceSystem}" /> Header="{x:Static p:Resources.Label_SourceSystem}" />
<DataGridTemplateColumn Header="{x:Static p:Resources.Label_SourceSystem}"> <DataGridTemplateColumn Header="{x:Static p:Resources.Label_SourceSystem}">
@@ -176,29 +181,38 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>--> </DataGridTemplateColumn>-->
<DataGridTextColumn Binding="{Binding FolderMonitor.EnableRaisingEvents, Converter={StaticResource MonitorStatusConverter}}" <DataGridTextColumn Binding="{Binding FolderMonitor.EnableRaisingEvents, Converter={StaticResource MonitorStatusConverter}}"
Header="{x:Static p:Resources.Label_Status}" /> Header="{x:Static p:Resources.Label_Status}" />
<DataGridTemplateColumn Header="{x:Static p:Resources.Label_Actions}"> <DataGridTemplateColumn Header="{x:Static p:Resources.Label_Actions}">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Button Command="{Binding DataContext.RemoveMonitoringPathCommand, <Button Command="{Binding DataContext.RemoveMonitoringPathCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
CommandParameter="{Binding .}" CommandParameter="{Binding .}"
Style="{StaticResource MaterialDesignOutlinedButton}" Style="{StaticResource MaterialDesignOutlinedButton}"
Margin="4" Margin="4"
Content="{x:Static p:Resources.Label_Remove}" /> Content="{x:Static p:Resources.Label_Remove}" />
<Button Command="{Binding DataContext.RestartMonitoringPathCommand, <Button Command="{Binding DataContext.RestartMonitoringPathCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
CommandParameter="{Binding .}" CommandParameter="{Binding .}"
Style="{StaticResource MaterialDesignOutlinedButton}" Style="{StaticResource MaterialDesignOutlinedButton}"
Margin="4" Margin="4"
Content="{x:Static p:Resources.Label_Restart}" /> Content="{x:Static p:Resources.Label_Restart}" />
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<TextBox Grid.Column="1"
Height="Auto"
Text="{Binding HttpServerLog}"
TextWrapping="Wrap"
AcceptsReturn="True"
/>
</Grid>
</DockPanel> </DockPanel>
</Window> </Window>