Added feature to auto allocate sales invoices to client purchase orders.

This commit is contained in:
Bobbie Hodgetts
2020-01-23 12:09:20 +00:00
parent 8680c2e5df
commit 773ce4cee5
36 changed files with 2278 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="BealeEngSQLDb" connectionString="Server=SQL-Server;Database=BealeEng;User Id=BealeEng Accounts;Password=3ddmur(wjS7fpjgveevs;" providerName="System.Data.SqlClient"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F025483F-53D1-47FC-9691-EB771FD845EF}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>BealeEngineering.Accounts</RootNamespace>
<AssemblyName>BealeEngineering.Accounts</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BealeEngineering.Core\BealeEngineering.Core.csproj">
<Project>{fd88a52a-fde5-4d0a-abdf-ee87d19f21bd}</Project>
<Name>BealeEngineering.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,61 @@
namespace BealeEngineering.Accounts
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnTest = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnTest
//
this.btnTest.Location = new System.Drawing.Point(61, 39);
this.btnTest.Name = "btnTest";
this.btnTest.Size = new System.Drawing.Size(139, 42);
this.btnTest.TabIndex = 0;
this.btnTest.Text = "Test it!";
this.btnTest.UseVisualStyleBackColor = true;
this.btnTest.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.btnTest);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnTest;
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration;
using BealeEngineering.Core;
namespace BealeEngineering.Accounts
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string conString = ConfigurationManager.ConnectionStrings["BealeEngSQLDb"].ToString();
var inst = new Core.Test.Autoexec(conString);
inst.Start();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BealeEngineering.Accounts
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BealeEngineering.Accounts")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BealeEngineering.Accounts")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f025483f-53d1-47fc-9691-eb771fd845ef")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BealeEngineering.Accounts.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BealeEngineering.Accounts.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BealeEngineering.Accounts.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FD88A52A-FDE5-4D0A-ABDF-EE87D19F21BD}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BealeEngineering.Core</RootNamespace>
<AssemblyName>BealeEngineering.Core</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dapper, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Dapper.2.0.30\lib\net461\Dapper.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Data\Database\Client\PurchaseOrderAllocationCreate.cs" />
<Compile Include="Data\Database\Client\PurchaseOrderGet.cs" />
<Compile Include="Data\Database\Client\PurchaseOrderAllocationGet.cs" />
<Compile Include="Data\Database\Sale\InvoiceGet.cs" />
<Compile Include="Data\Database\Sale\InvoiceHeaderGet.cs" />
<Compile Include="Logic\Client\PurchaseOrderAutoAllocate.cs" />
<Compile Include="Data\Database\Connection.cs" />
<Compile Include="Data\Database\Contact\ContactHeaderGet.cs" />
<Compile Include="Data\Database\Client\PurchaseOrderHeaderGet.cs" />
<Compile Include="Logic\Utilities\Reflection.cs" />
<Compile Include="Logic\Utilities\StringCheck.cs" />
<Compile Include="Model\Client\PurchaseOrder.cs" />
<Compile Include="Model\Client\PurchaseOrderHeader.cs" />
<Compile Include="Model\Client\PurchaseOrderLine.cs" />
<Compile Include="Model\Contact\ContactHeader.cs" />
<Compile Include="Model\Sale\Invoice.cs" />
<Compile Include="Model\Sale\InvoiceHeader.cs" />
<Compile Include="Model\Sale\InvoiceLine.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Test\Autoexec.cs" />
<Compile Include="Test\Client\PurchaseOrder.cs" />
<Compile Include="Test\Sales\Invoice.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Data\XeroAPI\" />
<Folder Include="Service\" />
<Folder Include="UI\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace BealeEngineering.Core.Data.Database.Client
{
public class PurchaseOrderAllocationCreate : Connection
{
public PurchaseOrderAllocationCreate(string sqlConnectionString) : base(sqlConnectionString)
{
}
public int ByDictionary(Dictionary<int, int> saleInvoiceIdToPoLineId)
{
int rowsCreated = 0;
if (saleInvoiceIdToPoLineId == null || !saleInvoiceIdToPoLineId.Any())
{
throw new Exception("No data passed to function.");
}
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
foreach (var item in saleInvoiceIdToPoLineId)
{
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO ClientPurchaseOrderLineSalesInvoice (
ClientPurchaseOrderLineID
,SaleInvoiceID
)
VALUES (
@clientPurchaseOrderLineID
,@saleInvoiceID
)
", conn))
{
cmd.Parameters.AddWithValue("@clientPurchaseOrderLineID", item.Value);
cmd.Parameters.AddWithValue("@saleInvoiceID", item.Key);
rowsCreated = rowsCreated + cmd.ExecuteNonQuery();
}
}
}
scope.Complete();
}
return rowsCreated;
}
}
}

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Data.Database.Client
{
public class PurchaseOrderAllocationGet : Connection
{
public PurchaseOrderAllocationGet(string sqlConnectionString) : base(sqlConnectionString)
{
}
public int GetUnallocatedInvoiceCount()
{
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT Count(SaleInvoice.SaleInvoiceID) AS CountOfSaleInvoiceID
FROM SaleInvoice
LEFT OUTER JOIN ClientPurchaseOrderLineSalesInvoice ON SaleInvoice.SaleInvoiceID = ClientPurchaseOrderLineSalesInvoice.SaleInvoiceID
WHERE (ClientPurchaseOrderLineSalesInvoice.SaleInvoiceID IS NULL)
AND (SaleInvoice.Reference IS NOT NULL)
", conn))
{
object obj = cmd.ExecuteScalar();
return (int)obj;
}
}
}
public List<int> GetUnallocatedInvoiceId()
{
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT SaleInvoice.SaleInvoiceID
FROM SaleInvoice
LEFT OUTER JOIN ClientPurchaseOrderLineSalesInvoice ON SaleInvoice.SaleInvoiceID = ClientPurchaseOrderLineSalesInvoice.SaleInvoiceID
WHERE (ClientPurchaseOrderLineSalesInvoice.SaleInvoiceID IS NULL)
AND (SaleInvoice.Reference IS NOT NULL)
", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
// do nothing
return null;
}
else
{
var returnList = new List<int>();
while (reader.Read())
{
returnList.Add(reader.GetInt32(0));
}
return returnList;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,102 @@
using Dapper;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Data.Database.Client
{
public class PurchaseOrderGet : PurchaseOrderHeaderGet
{
public PurchaseOrderGet(string sqlConnectionString) : base(sqlConnectionString)
{
}
public List<Model.Client.PurchaseOrderHeader> PurchaseOrderHeader { get; set; }
public bool PurchaseOrderHeaderIsSet
{
get
{
if (PurchaseOrderHeader == null || !PurchaseOrderHeader.Any()) { return false; }
else { return true; }
}
}
public new List<Model.Client.PurchaseOrder> GetByClientPurchaseOrderId(List<int> orderIdList)
{
ClientPurchaseOrderIdList = orderIdList;
try
{
return GetByFilters();
}
catch (Exception ex)
{
throw ex;
}
finally
{
ClientPurchaseOrderIdList = null;
}
}
public new List<Model.Client.PurchaseOrder> GetByFilters()
{
// build the sql string and dapper parameters
var parameters = new DynamicParameters();
string sqlString = @"
SELECT ClientPurchaseOrder.ClientPurchaseOrderID
,ClientPurchaseOrder.PurchaseOrderDate
,ClientPurchaseOrder.ContactID
,ClientPurchaseOrder.ClientReference
,ClientPurchaseOrder.RequestorEmail
,ClientPurchaseOrder.OrderTotal
,ClientPurchaseOrder.IsClosed
,ClientPurchaseOrderLine.ClientPurchaseOrderLineID
,ClientPurchaseOrderLine.LineNumber
,ClientPurchaseOrderLine.ProjectJobID
,ClientPurchaseOrderLine.Description
,ClientPurchaseOrderLine.LineNetAmount
FROM ClientPurchaseOrder
LEFT OUTER JOIN ClientPurchaseOrderLine ON ClientPurchaseOrder.ClientPurchaseOrderID = ClientPurchaseOrderLine.ClientPurchaseOrderID";
AddSqlWhereString(ref sqlString, ref parameters);
sqlString = sqlString + @"
ORDER BY ClientPurchaseOrder.ClientPurchaseOrderID
,ClientPurchaseOrderLine.LineNumber";
// make the call
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
var orderDictionary = new Dictionary<int, Model.Client.PurchaseOrder>();
var orderList = conn.Query<Model.Client.PurchaseOrder, Model.Client.PurchaseOrderLine, Model.Client.PurchaseOrder>
(
sqlString,
(order, orderDetail) =>
{
Model.Client.PurchaseOrder orderEntry;
if (!orderDictionary.TryGetValue(order.ClientPurchaseOrderID, out orderEntry))
{
orderEntry = order;
orderEntry.OrderLineList = new List<Model.Client.PurchaseOrderLine>();
orderDictionary.Add(orderEntry.ClientPurchaseOrderID, orderEntry);
}
orderEntry.OrderLineList.Add(orderDetail);
return orderEntry;
},
parameters,
splitOn: "ClientPurchaseOrderLineID")
.Distinct()
.ToList();
return orderList;
}
}
}
}

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Dapper;
namespace BealeEngineering.Core.Data.Database.Client
{
public class PurchaseOrderHeaderGet : Connection
{
public PurchaseOrderHeaderGet(string sqlConnectionString) : base(sqlConnectionString)
{
}
/// <summary>
/// Setting this will override he other filters, within the sql statement.
/// </summary>
protected List<int> ClientPurchaseOrderIdList { get; set; }
private bool ClientPurchaseOrderIdListIsSet
{
get
{
if (ClientPurchaseOrderIdList == null || !ClientPurchaseOrderIdList.Any()) { return false; }
else { return true; }
}
}
public DateTime DateFrom { get; set; }
public bool DateFromIsSet
{
get
{
if (DateFrom == null || DateFrom == default(DateTime)) { return false; }
else { return true; }
}
}
public DateTime DateTo { get; set; }
public bool DateToIsSet
{
get
{
if (DateTo == null || DateTo == default(DateTime)) { return false; }
else { return true; }
}
}
public List<string> Reference { get; set; }
public bool ReferenceIsSet
{
get
{
if (Reference == null || !Reference.Any()) { return false; }
else { return true; }
}
}
public bool ReturnIsClosed { get; set; } = true;
public List<Model.Client.PurchaseOrderHeader> GetByClientPurchaseOrderId(List<int> orderIdList)
{
ClientPurchaseOrderIdList = orderIdList;
try
{
return GetByFilters();
}
catch (Exception ex)
{
throw ex;
}
finally
{
ClientPurchaseOrderIdList = null;
}
}
protected void AddSqlWhereString(ref string sqlString, ref DynamicParameters parameters)
{
if (string.IsNullOrWhiteSpace(sqlString))
{ throw new Exception("SQL string is empty."); }
sqlString = sqlString + @"
WHERE 1=1";
if (ClientPurchaseOrderIdListIsSet)
{
sqlString = sqlString + @"
AND ClientPurchaseOrder.ClientPurchaseOrderID IN @purchaseOrderId";
parameters.Add("@purchaseOrderId", ClientPurchaseOrderIdList);
}
else
{
if (DateFromIsSet)
{
sqlString = sqlString + @"
AND PurchaseOrderDate >= @dateFrom";
parameters.Add("@dateFrom", DateFrom);
}
if (DateToIsSet)
{
sqlString = sqlString + @"
AND PurchaseOrderDate <= @dateTo";
parameters.Add("@dateTo", DateTo);
}
if (ReferenceIsSet)
{
sqlString = sqlString + @"
AND ClientReference IN @reference";
parameters.Add("@reference", Reference);
}
if (ReturnIsClosed == false)
{
sqlString = sqlString + @"
AND IsClosed = @isClosed";
parameters.Add("@isClosed", false);
}
}
}
public List<Model.Client.PurchaseOrderHeader> GetByFilters()
{
// build the sql string and dapper parameters
var parameters = new DynamicParameters();
string sqlString = @"
SELECT ClientPurchaseOrderID
,PurchaseOrderDate
,ContactID
,ClientReference
,RequestorEmail
,OrderTotal
,IsClosed
FROM ClientPurchaseOrder";
AddSqlWhereString(ref sqlString, ref parameters);
sqlString = sqlString + @"
ORDER BY ClientPurchaseOrderID";
// make the call
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
var purchaseOrders = conn.Query<Model.Client.PurchaseOrderHeader>(sqlString, parameters).ToList();
return purchaseOrders;
}
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Data.Database
{
public class Connection
{
protected readonly string sqlConnectionString;
public Connection(string sqlConnectionString)
{
// setup sql parameters
if (sqlConnectionString.Length == 0)
{ throw new Exception("Zero length sql connectionstring passed"); }
this.sqlConnectionString = sqlConnectionString;
}
}
}

View File

@@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Data.Database.Contact
{
public class ContactHeaderGet : Connection
{
public ContactHeaderGet(string sqlConnectionString) : base(sqlConnectionString)
{
}
private Dictionary<int, Model.Contact.ContactHeader> cacheContact = new Dictionary<int, Model.Contact.ContactHeader>();
public int NumberRequested = 0;
public int NumberRetrived = 0;
public int NumberRetrivedUnique = 0;
public int NumberFailed = 0;
public Model.Contact.ContactHeader ById(int contactId, bool cacheClear = false)
{
var contactIdList = new List<int>();
contactIdList.Add(contactId);
var resultList = ByIdList(contactIdList, cacheClear);
if (cacheContact.ContainsKey(contactId))
{
return cacheContact[contactId];
}
else
{
return null;
}
}
public Dictionary<int, Model.Contact.ContactHeader> ByIdList(List<int> contactIdList, bool cacheClear = false)
{
ClearStats();
// check list for values
if (!contactIdList.Any())
{
return null;
}
if (cacheClear)
{
cacheContact = new Dictionary<int, Model.Contact.ContactHeader>();
}
// build list of contactIds to lookup from db
var idLookupList = new List<int>();
foreach (int contactId in contactIdList)
{
if (!cacheContact.ContainsKey(contactId))
{
idLookupList.Add(contactId);
}
}
// query db and add to cache
if (idLookupList.Any())
{
//build sql string
string sqlString = null;
foreach (int id in idLookupList)
{
int count = 0;
if (count == 0)
{
sqlString = " WHERE ContactId=@contactId" + count;
}
else
{
sqlString = sqlString + " OR ContactId=@contactId" + count;
}
count = count + 1;
}
sqlString = @"
SELECT
ContactID
,ContactName
,EmailAddress
FROM Contact
" + sqlString;
// run query
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
{
foreach (int id in idLookupList)
{
int count = 0;
cmd.Parameters.AddWithValue("@contactId" + count, id);
count = count + 1;
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
// do something
}
else
{
while (reader.Read())
{
// load data into cache
var contact = new Model.Contact.ContactHeader();
contact.ContactId = reader.GetInt32(0);
contact.ContactName = reader.GetString(1);
contact.EmailAddress = reader.GetString(2);
if (cacheContact.ContainsKey(contact.ContactId))
{
cacheContact.Remove(contact.ContactId);
}
cacheContact.Add(contact.ContactId, contact);
}
}
}
}
}
}
// build and return list
var returnList = new Dictionary<int, Model.Contact.ContactHeader>();
foreach (var contactId in contactIdList)
{
NumberRequested = NumberRequested + 1;
if (cacheContact.ContainsKey(contactId))
{
if (!returnList.ContainsKey(contactId))
{
returnList.Add(contactId, cacheContact[contactId]);
}
}
else
{
NumberFailed = NumberFailed + 1;
}
}
NumberRetrived = NumberRequested - NumberFailed;
NumberRetrivedUnique = returnList.Count();
return returnList;
}
private void ClearStats()
{
NumberRequested = 0;
NumberRetrived = 0;
NumberRetrivedUnique = 0;
NumberFailed = 0;
}
}
}

View File

@@ -0,0 +1,111 @@
using Dapper;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Data.Database.Sale
{
public class InvoiceGet : InvoiceHeaderGet
{
public InvoiceGet(string sqlConnectionString) : base(sqlConnectionString)
{
}
public List<Model.Sale.InvoiceHeader> SaleInvoiceHeader { get; set; }
public bool SaleInvoiceHeaderIsSet
{
get
{
if (SaleInvoiceHeader == null || !SaleInvoiceHeader.Any()) { return false; }
else { return true; }
}
}
public new List<Model.Sale.Invoice> GetBySaleInvoiceId(List<int> invoiceIdList)
{
SalesInvoiceIdList = invoiceIdList;
try
{
return GetByFilters();
}
catch (Exception ex)
{
throw ex;
}
finally
{
SalesInvoiceIdList = null;
}
}
public new List<Model.Sale.Invoice> GetByFilters()
{
// build the sql string and dapper parameters
var parameters = new DynamicParameters();
string sqlString = @"
SELECT SaleInvoice.SaleInvoiceID
,SaleInvoice.ContactID
,SaleInvoice.SaleInvoiceNumber
,SaleInvoice.InvoiceDate
,SaleInvoice.DateDue
,SaleInvoice.Reference
,SaleInvoice.CurrencyCode
,SaleInvoice.InvoiceTotal
,SaleInvoice.TaxTotal
,SaleInvoiceLine.SaleInvoiceLineID
,SaleInvoiceLine.SaleInvoiceID
,SaleInvoiceLine.LineNumber
,SaleInvoiceLine.InventoryItemCode
,SaleInvoiceLine.Description
,SaleInvoiceLine.Quantity
,SaleInvoiceLine.UnitAmount
,SaleInvoiceLine.Discount
,SaleInvoiceLine.AccountCode
,SaleInvoiceLine.TaxType
,SaleInvoiceLine.TaxAmount
,SaleInvoiceLine.LineAmount
FROM SaleInvoice
LEFT OUTER JOIN SaleInvoiceLine ON SaleInvoice.SaleInvoiceID = SaleInvoiceLine.SaleInvoiceID";
AddSqlWhereString(ref sqlString, ref parameters);
sqlString = sqlString + @"
ORDER BY SaleInvoice.SaleInvoiceID
,SaleInvoiceLine.LineNumber
,SaleInvoiceLine.SaleInvoiceLineID";
// make the call
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
var invoiceDictionary = new Dictionary<int, Model.Sale.Invoice>();
var invoiceList = conn.Query<Model.Sale.Invoice, Model.Sale.InvoiceLine, Model.Sale.Invoice>
(
sqlString,
(invoice, invoiceDetail) =>
{
Model.Sale.Invoice invoiceEntry;
if (!invoiceDictionary.TryGetValue(invoice.SaleInvoiceID, out invoiceEntry))
{
invoiceEntry = invoice;
invoiceEntry.InvoiceLineList = new List<Model.Sale.InvoiceLine>();
invoiceDictionary.Add(invoiceEntry.SaleInvoiceID, invoiceEntry);
}
invoiceEntry.InvoiceLineList.Add(invoiceDetail);
return invoiceEntry;
},
parameters,
splitOn: "SaleInvoiceLineID")
.Distinct()
.ToList();
return invoiceList;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using Dapper;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Data.Database.Sale
{
public class InvoiceHeaderGet : Connection
{
public InvoiceHeaderGet(string sqlConnectionString) : base(sqlConnectionString)
{
}
/// <summary>
/// Setting this will override he other filters, within the sql statement.
/// </summary>
protected List<int> SalesInvoiceIdList { get; set; }
private bool SalesInvoiceIdListListIsSet
{
get
{
if (SalesInvoiceIdList == null || !SalesInvoiceIdList.Any()) { return false; }
else { return true; }
}
}
public DateTime DateFrom { get; set; }
public bool DateFromIsSet
{
get
{
if (DateFrom == null || DateFrom == default(DateTime)) { return false; }
else { return true; }
}
}
public DateTime DateTo { get; set; }
public bool DateToIsSet
{
get
{
if (DateTo == null || DateTo == default(DateTime)) { return false; }
else { return true; }
}
}
public List<string> InvoiceNumber { get; set; }
public bool InvoiceNumberIsSet
{
get
{
if (InvoiceNumber == null || !InvoiceNumber.Any()) { return false; }
else { return true; }
}
}
public List<string> Reference { get; set; }
public bool ReferenceIsSet
{
get
{
if (Reference == null || !Reference.Any()) { return false; }
else { return true; }
}
}
public List<Model.Sale.InvoiceHeader> GetBySaleInvoiceId(List<int> orderIdList)
{
SalesInvoiceIdList = orderIdList;
try
{
return GetByFilters();
}
catch (Exception ex)
{
throw ex;
}
finally
{
SalesInvoiceIdList = null;
}
}
protected void AddSqlWhereString(ref string sqlString, ref DynamicParameters parameters)
{
if (string.IsNullOrWhiteSpace(sqlString))
{ throw new Exception("SQL string is empty."); }
sqlString = sqlString + @"
WHERE 1=1";
if (SalesInvoiceIdListListIsSet)
{
sqlString = sqlString + @"
AND SaleInvoice.SaleInvoiceID IN @saleInvoiceId";
parameters.Add("@saleInvoiceId", SalesInvoiceIdList);
}
else
{
if (DateFromIsSet)
{
sqlString = sqlString + @"
AND InvoiceDate >= @dateFrom";
parameters.Add("@dateFrom", DateFrom);
}
if (DateToIsSet)
{
sqlString = sqlString + @"
AND InvoiceDate <= @dateTo";
parameters.Add("@dateTo", DateTo);
}
if (InvoiceNumberIsSet)
{
sqlString = sqlString + @"
AND SaleInvoiceNumber IN @salesInvoiceNumber";
parameters.Add("@salesInvoiceNumber", InvoiceNumber);
}
if (ReferenceIsSet)
{
sqlString = sqlString + @"
AND Reference IN @reference";
parameters.Add("@reference", Reference);
}
}
}
public List<Model.Sale.InvoiceHeader> GetByFilters()
{
// build the sql string and dapper parameters
var parameters = new DynamicParameters();
string sqlString = @"
SELECT SaleInvoiceID
,ContactID
,SaleInvoiceNumber
,InvoiceDate
,DateDue
,Reference
,CurrencyCode
,InvoiceTotal
,TaxTotal
,IsCreditNote
FROM SaleInvoice";
AddSqlWhereString(ref sqlString, ref parameters);
sqlString = sqlString + @"
ORDER BY SaleInvoiceID";
// make the call
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
var invoiceHeaders = conn.Query<Model.Sale.InvoiceHeader>(sqlString, parameters).ToList();
return invoiceHeaders;
}
}
}
}

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Logic.Client
{
public class PurchaseOrderAutoAllocate
{
public PurchaseOrderAutoAllocate(string sqlConnectionString)
{
SqlConnectionString = sqlConnectionString;
Init();
}
public bool IsComplete { get; private set; }
public int InvoiceMatched { get; private set; }
public int InvoiceProcessed { get; private set; }
public int InvoiceUnmatched
{
get { return InvoiceProcessed - InvoiceMatched; }
}
private string SqlConnectionString { get; set; }
public void Execute()
{
Init();
// get list of unallocated invoices
var poAlloInstance = new Data.Database.Client.PurchaseOrderAllocationGet(SqlConnectionString);
var invoiceIdList = poAlloInstance.GetUnallocatedInvoiceId();
// nothing to allocate
if (invoiceIdList == null || !invoiceIdList.Any())
{
IsComplete = true;
return;
}
else
{
InvoiceProcessed = invoiceIdList.Count();
}
// get invoice header info
var invoiceInst = new Data.Database.Sale.InvoiceHeaderGet(SqlConnectionString);
var invoiceList = invoiceInst.GetBySaleInvoiceId(invoiceIdList);
// create lookup list for matching
var lookupList = new List<Tuple<Model.Sale.InvoiceHeader, string, int?>>();
for (int i = 0; i < invoiceList.Count; i++)
{
lookupList.Add(new Tuple<Model.Sale.InvoiceHeader, string, int?>
(invoiceList[i], invoiceList[i].Reference, null));
// check if a line number can be potentially parsed off reference
// if it can, add a second lookup entry (leave the first as it might be right)
string parsedReference = string.Copy(invoiceList[i].Reference);
int? parsedLineNumber = null;
ParseOutLineNumbes(ref parsedReference, ref parsedLineNumber);
if (parsedLineNumber != null)
{
lookupList.Add(new Tuple<Model.Sale.InvoiceHeader, string, int?>
(invoiceList[i], parsedReference, parsedLineNumber));
}
}
// for PO with multiple lines, sort lookup list with potential parsed line numbers first
// try to match on ref and line# first, then try ref and line total
lookupList = lookupList.OrderByDescending(t => t.Item3).ToList();
//get client POs from db that match reference list
var referenceList = new List<string>();
foreach(var item in lookupList) { referenceList.Add(item.Item2); }
var poInstance = new Data.Database.Client.PurchaseOrderGet(SqlConnectionString);
poInstance.Reference = referenceList.Distinct().ToList();
poInstance.ReturnIsClosed = true; // <--------------------------------------------------change to false after
var clientPoList = poInstance.GetByFilters();
// create dictionary for matched items
var invoiceIdToPoLineId = new Dictionary<int, int>();
// loop through list and do the matching
for (int i = 0; i < lookupList.Count; i++)
{
// skip any invoice ids already done
int invoiceId = lookupList[i].Item1.SaleInvoiceID;
if (!invoiceIdToPoLineId.ContainsKey(invoiceId))
{
// match contact ID
foreach (var po in clientPoList)
{
if (po.ContactID == lookupList[i].Item1.ContactID)
{
// match PO reference
string reference = lookupList[i].Item2;
if (po.ClientReference == reference)
{
// match PO line(s)
int? parsedLineNumber = lookupList[i].Item3;
// only one line in PO, jus match invoice to it
if (po.OrderLineCount == 1)
{
invoiceIdToPoLineId.Add(invoiceId, po.OrderLineList.First().ClientPurchaseOrderLineID);
}
// for multiple line, try to match invoice to line number
else if (po.OrderLineCount > 1 && parsedLineNumber != null)
{
foreach (var line in po.OrderLineList)
{
if (line.LineNumber == parsedLineNumber)
{
invoiceIdToPoLineId.Add(invoiceId, line.ClientPurchaseOrderLineID);
}
}
}
// for multiple line, try to match invoice to line total
else if(po.OrderLineCount > 1 && parsedLineNumber == null)
{
int matchCount = 0;
int poLineId = 0;
decimal invoiceNetTotal = lookupList[i].Item1.InvoiceTotal - lookupList[i].Item1.TaxTotal;
foreach (var line in po.OrderLineList)
{
if (line.LineNetAmount == invoiceNetTotal)
{
matchCount = matchCount + 1;
poLineId = line.ClientPurchaseOrderLineID;
}
}
// only do match if one line is the same
if (matchCount == 1)
{
invoiceIdToPoLineId.Add(invoiceId, poLineId);
}
}
}
}
}
}
}
// update db table
if (invoiceIdToPoLineId.Count > 0)
{
var instance2 = new Data.Database.Client.PurchaseOrderAllocationCreate(SqlConnectionString);
InvoiceMatched = instance2.ByDictionary(invoiceIdToPoLineId);
}
IsComplete = true;
}
public void Init()
{
IsComplete = false;
InvoiceMatched = 0;
InvoiceProcessed = 0;
}
/// <summary>
/// Parses out any possible line numbers from end of PO reference and adds to them the end of the reference list.
/// </summary>
/// <param name="reference"></param>
/// <returns></returns>
private void ParseOutLineNumbes(ref string reference, ref int? lineNumber)
{
int dashIndex = reference.LastIndexOf('-');
if (dashIndex > 0)
{
var newReference = reference.Substring(0, dashIndex);
if (newReference != reference)
{
string lineNoString = reference.Substring(dashIndex + 1);
int lineNoInt = 0;
if (Int32.TryParse(lineNoString, out lineNoInt))
{
// it can, and the end string can be converted into an int, so we add it.
reference = newReference;
lineNumber = lineNoInt;
}
}
}
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Reflection;
namespace BealeEngineering.Core.Logic.Utilities
{
public static class Reflection
{
/// <summary>
/// Extension for 'Object' that copies the properties to a destination object.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="destination">The destination.</param>
public static void CopyProperties(this object source, object destination)
{
// If any this null throw an exception
if (source == null || destination == null)
throw new Exception("Source or/and Destination Objects are null");
// Getting the Types of the objects
Type typeDest = destination.GetType();
Type typeSrc = source.GetType();
// Iterate the Properties of the source instance and
// populate them from their desination counterparts
PropertyInfo[] srcProps = typeSrc.GetProperties();
foreach (PropertyInfo srcProp in srcProps)
{
if (!srcProp.CanRead)
{
continue;
}
PropertyInfo targetProperty = typeDest.GetProperty(srcProp.Name);
if (targetProperty == null)
{
continue;
}
if (!targetProperty.CanWrite)
{
continue;
}
if (targetProperty.GetSetMethod(true) != null && targetProperty.GetSetMethod(true).IsPrivate)
{
continue;
}
if ((targetProperty.GetSetMethod().Attributes & MethodAttributes.Static) != 0)
{
continue;
}
if (!targetProperty.PropertyType.IsAssignableFrom(srcProp.PropertyType))
{
continue;
}
// Passed all tests, lets set the value
targetProperty.SetValue(destination, srcProp.GetValue(source, null), null);
}
}
}
}
/* https://stackoverflow.com/questions/930433
* USAGE:
*
/// <summary>
/// ExampleCopyObject
/// </summary>
/// <returns></returns>
public object ExampleCopyObject()
{
object destObject = new object();
this.CopyProperties(destObject); // inside a class you want to copy from
Reflection.CopyProperties(this, destObject); // Same as above but directly calling the function
TestClass srcClass = new TestClass();
TestStruct destStruct = new TestStruct();
srcClass.CopyProperties(destStruct); // using the extension directly on a object
Reflection.CopyProperties(srcClass, destObject); // Same as above but directly calling the function
//so on and so forth.... your imagination is the limits :D
return srcClass;
}
public class TestClass
{
public string Blah { get; set; }
}
public struct TestStruct
{
public string Blah { get; set; }
}
*/

View File

@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Logic.Utilities
{
class StringCheck
{
public bool AllowEmpty { get; set; } = false;
public bool AllowWhiteSpace { get; set; } = false;
public string ErrorMessage { get; private set; }
public void ResetToDefault()
{
ErrorMessage = null;
AllowEmpty = false;
AllowWhiteSpace = false;
}
public bool IsAlpha(string stringToCheck, bool upperCaseOnly = false, bool allowNull = false)
{
ErrorMessage = null;
if (stringToCheck == null)
{
if (!allowNull)
{
ErrorMessage = "String is null";
return false;
}
}
else
{
foreach (char c in stringToCheck)
{
if (!((c >= 'A' && c <= 'Z')
|| ((c >= 'a' && c <= 'z') && !upperCaseOnly)))
{
if ((c >= 'a' && c <= 'z') && upperCaseOnly)
{
ErrorMessage = "String contains lower case numerical charater(s).";
return false;
}
else
{
ErrorMessage = "String contains non-alpha charater(s).";
return false;
}
}
}
}
return true;
}
public bool IsAlphaNumeric(string stringToCheck, bool upperCaseOnly = false, bool allowNull = false)
{
ErrorMessage = null;
if (stringToCheck == null)
{
if (!allowNull)
{
ErrorMessage = "String is null";
return false;
}
}
else
{
foreach (char c in stringToCheck)
{
if (!((c >= '0' && c <= '9')
|| (c >= 'A' && c <= 'Z')
|| ((c >= 'a' && c <= 'z') && !upperCaseOnly)))
{
if ((c >= 'a' && c <= 'z') && upperCaseOnly)
{
ErrorMessage = "String contains lower case numerical charater(s).";
return false;
}
else
{
ErrorMessage = "String contains non-alphanumeric charater(s).";
return false;
}
}
}
}
return true;
}
public bool IsNumeric(string stringToCheck, bool allowNull = false)
{
ErrorMessage = null;
if (stringToCheck == null)
{
if (allowNull == false)
{
ErrorMessage = "String is null";
return false;
}
}
else
{
foreach (char c in stringToCheck)
{
if (c < '0' || c > '9')
{
ErrorMessage = "String contains non-numeric charater(s).";
return false;
}
}
}
return true;
}
public bool Length(string stringToCheck, int stringLength, bool allowNull = false)
{
ErrorMessage = null;
if (!NullOrWhiteSpaceCheck(stringToCheck, allowNull))
{
return false;
}
int length = stringToCheck.Length;
if (length != stringLength)
{
ErrorMessage = "String length (" + length + ") does not equal " + stringLength + " charaters.";
return false;
}
return true;
}
public bool MaxLength(string stringToCheck, int maxLength, bool allowNull = false)
{
ErrorMessage = null;
if (!NullOrWhiteSpaceCheck(stringToCheck, allowNull))
{
return false;
}
int length = stringToCheck.Length;
if (length > maxLength)
{
ErrorMessage = "String length (" + length + ") is greater than " + maxLength + " charaters.";
return false;
}
return true;
}
public bool MinLength(string stringToCheck, int minLength, bool allowNull = false)
{
ErrorMessage = null;
if (!NullOrWhiteSpaceCheck(stringToCheck, allowNull))
{
return false;
}
int length = stringToCheck.Length;
if (length <= minLength)
{
ErrorMessage = "String length (" + length + ") is less than " + minLength + " charaters.";
return false;
}
return true;
}
private bool NullOrWhiteSpaceCheck(string stringToCheck, bool allowNull = false)
{
ErrorMessage = null;
if (string.IsNullOrWhiteSpace(stringToCheck))
{
if (stringToCheck == null)
{
if (!allowNull)
{
ErrorMessage = "String is null, empty or white space.";
return false;
}
}
else if (stringToCheck == "")
{
if (!AllowEmpty)
{
ErrorMessage = "String is empty.";
return false;
}
}
else
{
if (!AllowWhiteSpace)
{
ErrorMessage = "String is white space.";
return false;
}
}
}
return true;
}
}
}

View File

@@ -0,0 +1,20 @@
using BealeEngineering.Core.Logic.Utilities;
using System;
using System.Collections.Generic;
using System.Text;
namespace BealeEngineering.Core.Model.Client
{
public class PurchaseOrder : PurchaseOrderHeader
{
public int OrderLineCount
{
get
{
if (OrderLineList == null) { return 0; }
else { return OrderLineList.Count; }
}
}
public List<Client.PurchaseOrderLine> OrderLineList { get; set; }
}
}

View File

@@ -0,0 +1,38 @@
using BealeEngineering.Core.Logic.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Model.Client
{
public class PurchaseOrderHeader
{
public int ClientPurchaseOrderID { get; set; }
public DateTime PurchaseOrderDate { get; set; }
public int ContactID { get; set; }
public string ClientReference { get; set; }
public string RequestorEmail { get; set; }
public decimal OrderTotal { get; set; }
public bool IsClosed { get; set; }
//sealed PurchaseOrder CreatePurchaseOrder()
//{
// PurchaseOrder destObject = new PurchaseOrder();
// this.CopyProperties(destObject); // inside a class you want to copy from
// return destObject;
// Reflection.CopyProperties(this, destObject); // Same as above but directly calling the function
// TestClass srcClass = new TestClass();
// TestStruct destStruct = new TestStruct();
// srcClass.CopyProperties(destStruct); // using the extension directly on a object
// Reflection.CopyProperties(srcClass, destObject); // Same as above but directly calling the function
// //so on and so forth.... your imagination is the limits :D
// return srcClass;
//}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BealeEngineering.Core.Model.Client
{
public class PurchaseOrderLine
{
public int ClientPurchaseOrderLineID { get; set; }
public int ClientPurchaseOrderID { get; set; }
public int LineNumber { get; set; }
public int ProjectJobID { get; set; }
public string Description { get; set; }
public decimal LineNetAmount { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Model.Contact
{
public class ContactHeader
{
public int ContactId { get; set; }
public string ContactName { get; set; }
public string EmailAddress { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Model.Sale
{
public class Invoice : InvoiceHeader
{
public List<Model.Sale.InvoiceLine> InvoiceLineList { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Model.Sale
{
public class InvoiceHeader
{
public int SaleInvoiceID { get; set; }
public int ContactID { get; set; }
public string SaleInvoiceNumber { get; set; }
public DateTime InvoiceDate { get; set; }
public DateTime DueDate { get; set; }
public string Reference { get; set; }
public string CurrencyCode { get; set; }
public decimal InvoiceTotal { get; set;}
public decimal TaxTotal { get; set; }
public bool IsCreditNote { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Model.Sale
{
public class InvoiceLine
{
public int SaleInvoiceLineID { get; set; }
public int SaleInvoiceID { get; set; }
public string InventoryItemCode { get; set; }
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitAmount { get; set; }
public int Discount { get; set; }
public string AccountCode { get; set; }
public string TaxType { get; set; }
public decimal TaxAmount { get; set; }
public decimal LineAmount { get; set; }
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BealeEngineering.Core")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BealeEngineering.Core")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("fd88a52a-fde5-4d0a-abdf-ee87d19f21bd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Test
{
public class Autoexec
{
public Autoexec(string sqlConnectionString)
{
SqlConnectionString = sqlConnectionString;
}
private string SqlConnectionString { get; set; }
public void Start()
{
// thing you want to run from the form button
//var inst = new Core.Test.Sales.Invoice(SqlConnectionString);
//inst.GetInvoice();
var inst2 = new Test.Client.PurchaseOrder(SqlConnectionString);
inst2.AllocateInvoicesToPurchaseOrders();
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Test.Client
{
public class PurchaseOrder
{
public List<int> PurchaseOrderIdList { get; set; }
public string SqlConnectionString { get; set; }
public PurchaseOrder(string sqlConnectionString)
{
SqlConnectionString = sqlConnectionString;
PurchaseOrderIdList = new List<int> { 92, 17, 140 };
}
public void Start()
{
GetPurchaseOrderById();
}
public void GetPurchaseOrderById()
{
var inst = new Core.Data.Database.Client.PurchaseOrderGet(SqlConnectionString);
var newList = inst.GetByClientPurchaseOrderId(PurchaseOrderIdList);
}
public void AllocateInvoicesToPurchaseOrders()
{
var inst = new Logic.Client.PurchaseOrderAutoAllocate(SqlConnectionString);
inst.Execute();
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BealeEngineering.Core.Test.Sales
{
public class Invoice
{
public Invoice(string sqlConnectionString)
{
SqlConnectionString = sqlConnectionString;
SaleInvoiceIdList = new List<int> { 131, 481, 105, 324 };
}
private string SqlConnectionString { get; set; }
public List<int> SaleInvoiceIdList { get; set; }
public void GetInvoice()
{
var InvInst = new Data.Database.Sale.InvoiceGet(SqlConnectionString);
var lkdjflsk = InvInst.GetBySaleInvoiceId(SaleInvoiceIdList);
}
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Dapper" version="2.0.30" targetFramework="net472" />
</packages>

View File

@@ -0,0 +1,33 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29306.81
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{BC929CBA-5FE7-4A75-9AED-B4699E340B0D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BealeEngineering.Accounts", "BealeEngineering.Accounts\BealeEngineering.Accounts.csproj", "{F025483F-53D1-47FC-9691-EB771FD845EF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BealeEngineering.Core", "BealeEngineering.Core\BealeEngineering.Core.csproj", "{FD88A52A-FDE5-4D0A-ABDF-EE87D19F21BD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F025483F-53D1-47FC-9691-EB771FD845EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F025483F-53D1-47FC-9691-EB771FD845EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F025483F-53D1-47FC-9691-EB771FD845EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F025483F-53D1-47FC-9691-EB771FD845EF}.Release|Any CPU.Build.0 = Release|Any CPU
{FD88A52A-FDE5-4D0A-ABDF-EE87D19F21BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD88A52A-FDE5-4D0A-ABDF-EE87D19F21BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD88A52A-FDE5-4D0A-ABDF-EE87D19F21BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD88A52A-FDE5-4D0A-ABDF-EE87D19F21BD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0583C62C-021B-4409-A7C8-85463F2CEA0C}
EndGlobalSection
EndGlobal