mirror of
https://github.com/stokebob/BealeEngineering.git
synced 2026-03-21 15:47:15 +00:00
Import Xero sales invoice flat-file
Feature complete and tested
This commit is contained in:
@@ -24,7 +24,6 @@ namespace BealeEngineering.Accounts
|
||||
string conString = ConfigurationManager.ConnectionStrings["BealeEngSQLDb"].ToString();
|
||||
|
||||
var inst = new Core.Test.Autoexec(conString);
|
||||
inst.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
@@ -50,6 +51,7 @@
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@@ -58,38 +60,44 @@
|
||||
<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="Data\Xero\SaleInvoiceGet.cs" />
|
||||
<Compile Include="Data\Database\Client\CreatePurchaseOrderAllocation.cs" />
|
||||
<Compile Include="Data\Database\Client\ReadPurchaseOrder.cs" />
|
||||
<Compile Include="Data\Database\Client\ReadPurchaseOrderAllocation.cs" />
|
||||
<Compile Include="Data\Database\Contact\UpdateContact.cs" />
|
||||
<Compile Include="Data\Database\Sale\CreateInvoice.cs" />
|
||||
<Compile Include="Data\Database\Sale\UpdateInvoice.cs" />
|
||||
<Compile Include="Model\Contact\Address.cs" />
|
||||
<Compile Include="Data\Database\Contact\CreateContact.cs" />
|
||||
<Compile Include="Data\Database\Sale\ReadInvoice.cs" />
|
||||
<Compile Include="Data\Database\Sale\ReadInvoiceHeader.cs" />
|
||||
<Compile Include="Data\Xero\ReadXeroInvoiceFlatFile.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\Import\wipXeroInvoiceFlatFile.cs" />
|
||||
<Compile Include="Data\Database\Contact\ReadContact.cs" />
|
||||
<Compile Include="Data\Database\Client\ReadPurchaseOrderHeader.cs" />
|
||||
<Compile Include="Logic\Import\XeroInvoiceFlatFile.cs" />
|
||||
<Compile Include="Logic\Utilities\CSVGetRFC4180Compliant.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\Contact\Contact.cs" />
|
||||
<Compile Include="Model\Import\XeroInvoiceFlatFile.cs" />
|
||||
<Compile Include="Model\Import\XeroInvoiceFlatFileDTO.cs" />
|
||||
<Compile Include="Model\Sale\Invoice.cs" />
|
||||
<Compile Include="Model\Sale\InvoiceHeader.cs" />
|
||||
<Compile Include="Model\Sale\InvoiceLine.cs" />
|
||||
<Compile Include="Model\ValidateModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Test\Autoexec.cs" />
|
||||
<Compile Include="Test\Client\PurchaseOrder.cs" />
|
||||
<Compile Include="Test\Contact\Contact.cs" />
|
||||
<Compile Include="Test\Import\ImportFlatfile.cs" />
|
||||
<Compile Include="Test\Sales\Invoice.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\Xero\FlatFile\" />
|
||||
<Folder Include="Service\" />
|
||||
<Folder Include="Logic\Sale\" />
|
||||
<Folder Include="Service\Contact\" />
|
||||
<Folder Include="UI\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -8,9 +8,9 @@ using System.Transactions;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Client
|
||||
{
|
||||
public class PurchaseOrderAllocationCreate : Connection
|
||||
public class CreatePurchaseOrderAllocation : Connection
|
||||
{
|
||||
public PurchaseOrderAllocationCreate(string sqlConnectionString) : base(sqlConnectionString)
|
||||
public CreatePurchaseOrderAllocation(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -9,9 +9,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Client
|
||||
{
|
||||
public class PurchaseOrderGet : PurchaseOrderHeaderGet
|
||||
public class ReadPurchaseOrder : ReadPurchaseOrderHeader
|
||||
{
|
||||
public PurchaseOrderGet(string sqlConnectionString) : base(sqlConnectionString)
|
||||
public ReadPurchaseOrder(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace BealeEngineering.Core.Data.Database.Client
|
||||
|
||||
var orderDictionary = new Dictionary<int, Model.Client.PurchaseOrder>();
|
||||
|
||||
var orderList = conn.Query<Model.Client.PurchaseOrder, Model.Client.PurchaseOrderLine, Model.Client.PurchaseOrder>
|
||||
var orderList = conn.Query<Model.Client.PurchaseOrder, Model.Client.PurchaseOrder.PurchaseOrderLine, Model.Client.PurchaseOrder>
|
||||
(
|
||||
sqlString,
|
||||
(order, orderDetail) =>
|
||||
@@ -83,7 +83,7 @@ namespace BealeEngineering.Core.Data.Database.Client
|
||||
if (!orderDictionary.TryGetValue(order.ClientPurchaseOrderID, out orderEntry))
|
||||
{
|
||||
orderEntry = order;
|
||||
orderEntry.OrderLineList = new List<Model.Client.PurchaseOrderLine>();
|
||||
orderEntry.OrderLineList = new List<Model.Client.PurchaseOrder.PurchaseOrderLine>();
|
||||
orderDictionary.Add(orderEntry.ClientPurchaseOrderID, orderEntry);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Client
|
||||
{
|
||||
public class PurchaseOrderAllocationGet : Connection
|
||||
public class ReadPurchaseOrderAllocation : Connection
|
||||
{
|
||||
public PurchaseOrderAllocationGet(string sqlConnectionString) : base(sqlConnectionString)
|
||||
public ReadPurchaseOrderAllocation(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -8,9 +8,9 @@ using Dapper;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Client
|
||||
{
|
||||
public class PurchaseOrderHeaderGet : Connection
|
||||
public class ReadPurchaseOrderHeader : Connection
|
||||
{
|
||||
public PurchaseOrderHeaderGet(string sqlConnectionString) : base(sqlConnectionString)
|
||||
public ReadPurchaseOrderHeader(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database
|
||||
{
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Dapper;
|
||||
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.Contact
|
||||
{
|
||||
public class CreateContact : Connection
|
||||
{
|
||||
public CreateContact(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
public void ByContact(Model.Contact.Contact contact)
|
||||
{
|
||||
var list = new List<Model.Contact.Contact> { contact };
|
||||
ByContactList(list);
|
||||
}
|
||||
public void ByContactList(List<Model.Contact.Contact> contactList)
|
||||
{
|
||||
var updateContact = new UpdateContact(sqlConnectionString);
|
||||
updateContact.ByContactList(contactList, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using Dapper;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Contact
|
||||
{
|
||||
public class ReadContact : Connection
|
||||
{
|
||||
public ReadContact(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
CacheInnit();
|
||||
}
|
||||
private Dictionary<int, Model.Contact.Contact> cacheId;
|
||||
private Dictionary<string, int> cacheName;
|
||||
public Model.Contact.Contact ByContactId(int contactId, bool cacheClear = false)
|
||||
{
|
||||
var contactIdList = new List<int>();
|
||||
contactIdList.Add(contactId);
|
||||
var resultList = ByContactId(contactIdList, cacheClear);
|
||||
if (resultList == null || !resultList.Any())
|
||||
{ return null; }
|
||||
else
|
||||
{ return resultList[0]; }
|
||||
}
|
||||
public List<Model.Contact.Contact> ByContactId(List<int> contactIdList, bool cacheClear = false)
|
||||
{
|
||||
if (cacheClear)
|
||||
{ CacheInnit(); }
|
||||
|
||||
if (!contactIdList.Any())
|
||||
{ return null; }
|
||||
|
||||
// find items not in cache
|
||||
var dbQuery = new List<int>();
|
||||
foreach (var id in contactIdList)
|
||||
{
|
||||
if (!cacheId.ContainsKey(id))
|
||||
{ dbQuery.Add(id); }
|
||||
}
|
||||
|
||||
// populate cache with values from db
|
||||
if (dbQuery.Any())
|
||||
{
|
||||
string whereString = @"
|
||||
AND ContactID IN @contactID";
|
||||
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("@contactID", dbQuery);
|
||||
|
||||
Execute(whereString, parameters);
|
||||
}
|
||||
|
||||
// query chache for return
|
||||
var returnList = new List<Model.Contact.Contact>();
|
||||
foreach (var id in contactIdList)
|
||||
{
|
||||
if (cacheId.ContainsKey(id))
|
||||
{ returnList.Add(cacheId[id]); }
|
||||
}
|
||||
|
||||
if (returnList.Any())
|
||||
{ return returnList; }
|
||||
else
|
||||
{ return null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get contact by unique contact name.
|
||||
/// </summary>
|
||||
/// <param name="contactName">Unique contact name</param>
|
||||
/// <param name="cacheClear">Force database read</param>
|
||||
/// <returns>Contact Header information</returns>
|
||||
public Model.Contact.Contact ByContactName(string contactName, bool cacheClear = false)
|
||||
{
|
||||
var contactNameList = new List<string>();
|
||||
contactNameList.Add(contactName);
|
||||
var resultList = ByContactName(contactNameList, cacheClear);
|
||||
if (resultList == null || !resultList.Any())
|
||||
{ return null; }
|
||||
else
|
||||
{ return resultList[0]; }
|
||||
}
|
||||
public List<Model.Contact.Contact> ByContactName(List<string> contactNameList, bool cacheClear = false)
|
||||
{
|
||||
if (cacheClear)
|
||||
{ CacheInnit(); }
|
||||
|
||||
if (!contactNameList.Any())
|
||||
{ return null; }
|
||||
|
||||
// find items not in cache
|
||||
List<string> dbQuery = new List<string>();
|
||||
foreach (var name in contactNameList)
|
||||
{
|
||||
if (!cacheName.ContainsKey(name))
|
||||
{ dbQuery.Add(name); }
|
||||
}
|
||||
|
||||
// populate cache with values from db
|
||||
if (dbQuery.Any())
|
||||
{
|
||||
string whereString = @"
|
||||
AND ContactName IN @contactName";
|
||||
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("@contactName", dbQuery);
|
||||
|
||||
Execute(whereString, parameters);
|
||||
}
|
||||
|
||||
// query chache for return
|
||||
var returnList = new List<Model.Contact.Contact>();
|
||||
foreach (var name in contactNameList)
|
||||
{
|
||||
if (cacheName.ContainsKey(name))
|
||||
{ returnList.Add(cacheId[cacheName[name]]); }
|
||||
}
|
||||
|
||||
if (returnList.Any())
|
||||
{ return returnList; }
|
||||
else
|
||||
{ return null; }
|
||||
}
|
||||
private void CacheAdd(Model.Contact.Contact contact)
|
||||
{
|
||||
if (cacheId.ContainsKey(contact.ContactId))
|
||||
{ CacheRemove(contact); }
|
||||
cacheId.Add(contact.ContactId, contact);
|
||||
cacheName.Add(contact.ContactName, contact.ContactId);
|
||||
}
|
||||
private void CacheInnit()
|
||||
{
|
||||
cacheId = new Dictionary<int, Model.Contact.Contact>();
|
||||
cacheName = new Dictionary<string, int>();
|
||||
}
|
||||
private void CacheRemove(Model.Contact.Contact contact)
|
||||
{
|
||||
cacheId.Remove(contact.ContactId);
|
||||
cacheName.Remove(contact.ContactName);
|
||||
|
||||
}
|
||||
private void Execute(string sqlWhere, DynamicParameters parameters)
|
||||
{
|
||||
var contactList = new List<Model.Contact.Contact>();
|
||||
|
||||
string sqlString = @"
|
||||
SELECT
|
||||
[ContactID]
|
||||
,[ContactName]
|
||||
,[EmailAddress]
|
||||
,[PrimaryPersonFirstName]
|
||||
,[PrimaryPersonSurname]
|
||||
,[PrimaryPersonEmail]
|
||||
,[POAddressLine1] AS AddressLine1
|
||||
,[POAddressLine2] AS AddressLine2
|
||||
,[POAddressLine3] AS AddressLine3
|
||||
,[POAddressLine4] AS AddressLine4
|
||||
,[POAddressCity] AS City
|
||||
,[POAddressRegion] AS Region
|
||||
,[POAddressPostalCode] AS PostalCode
|
||||
,[POAddressCountry] AS Country
|
||||
FROM Contact
|
||||
WHERE 1=1" + sqlWhere;
|
||||
|
||||
// make the call
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
contactList = conn.Query<Model.Contact.Contact, Model.Contact.Address, Model.Contact.Contact>
|
||||
(
|
||||
sqlString,
|
||||
(contact, address) =>
|
||||
{
|
||||
contact.PostalAddress = address;
|
||||
return contact;
|
||||
},
|
||||
parameters,
|
||||
splitOn: "AddressLine1")
|
||||
.Distinct()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
foreach (var contact in contactList)
|
||||
{
|
||||
CacheAdd(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
using Dapper;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Contact
|
||||
{
|
||||
public class UpdateContact : Connection
|
||||
{
|
||||
public UpdateContact(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
public void ByContact(Model.Contact.Contact contact, bool insertNew = false)
|
||||
{
|
||||
var list = new List<Model.Contact.Contact> { contact };
|
||||
ByContactList(list, insertNew);
|
||||
}
|
||||
public void ByContactList(List<Model.Contact.Contact> contactList, bool insertNew = false)
|
||||
{
|
||||
// check the list
|
||||
CheckList(ref contactList);
|
||||
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
foreach (var contact in contactList)
|
||||
{
|
||||
// build the sql string
|
||||
string sqlString = @"
|
||||
UPDATE Contact
|
||||
SET
|
||||
[ContactName] = @contactName
|
||||
,[EmailAddress] = @emailAddress
|
||||
,[PrimaryPersonFirstName] = @primaryPersonFirstName
|
||||
,[PrimaryPersonSurname] = @primaryPersonSurname
|
||||
,[PrimaryPersonEmail] = @primaryPersonEmail
|
||||
,[POAddressLine1] = @poAddressLine1
|
||||
,[POAddressLine2] = @poAddressLine2
|
||||
,[POAddressLine3] = @poAddressLine3
|
||||
,[POAddressLine4] = @poAddressLine4
|
||||
,[POAddressCity] = @poAddressCity
|
||||
,[POAddressRegion] = @poAddressRegion
|
||||
,[POAddressPostalCode] = @poAddressPostalCode
|
||||
,[POAddressCountry] = @poAddressCountry
|
||||
WHERE ContactName = @contactName";
|
||||
|
||||
if (insertNew)
|
||||
{
|
||||
sqlString = sqlString + @"
|
||||
IF @@ROWCOUNT = 0
|
||||
INSERT INTO Contact(
|
||||
[ContactName]
|
||||
,[EmailAddress]
|
||||
,[PrimaryPersonFirstName]
|
||||
,[PrimaryPersonSurname]
|
||||
,[PrimaryPersonEmail]
|
||||
,[POAddressLine1]
|
||||
,[POAddressLine2]
|
||||
,[POAddressLine3]
|
||||
,[POAddressLine4]
|
||||
,[POAddressCity]
|
||||
,[POAddressRegion]
|
||||
,[POAddressPostalCode]
|
||||
,[POAddressCountry]
|
||||
)
|
||||
VALUES(
|
||||
@contactName
|
||||
,@emailAddress
|
||||
,@primaryPersonFirstName
|
||||
,@primaryPersonSurname
|
||||
,@primaryPersonEmail
|
||||
,@poAddressLine1
|
||||
,@poAddressLine2
|
||||
,@poAddressLine3
|
||||
,@poAddressLine4
|
||||
,@poAddressCity
|
||||
,@poAddressRegion
|
||||
,@poAddressPostalCode
|
||||
,@poAddressCountry
|
||||
)";
|
||||
}
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@contactName", contact.ContactName);
|
||||
if (!string.IsNullOrWhiteSpace(contact.EmailAddress))
|
||||
{ cmd.Parameters.AddWithValue("@emailAddress", contact.EmailAddress); }
|
||||
else { cmd.Parameters.AddWithValue("@emailAddress", DBNull.Value); }
|
||||
cmd.Parameters.AddWithValue("@primaryPersonFirstName", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@primaryPersonSurname", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@primaryPersonEmail", DBNull.Value);
|
||||
if (contact.PostalAddressIsSet)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.AddressLine1))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressLine1", contact.PostalAddress.AddressLine1); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressLine1", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.AddressLine2))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressLine2", contact.PostalAddress.AddressLine2); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressLine2", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.AddressLine3))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressLine3", contact.PostalAddress.AddressLine3); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressLine3", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.AddressLine4))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressLine4", contact.PostalAddress.AddressLine4); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressLine4", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.City))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressCity", contact.PostalAddress.City); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressCity", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.Region))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressRegion", contact.PostalAddress.Region); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressRegion", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.PostalCode))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressPostalCode", contact.PostalAddress.PostalCode); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressPostalCode", DBNull.Value); }
|
||||
if (!string.IsNullOrWhiteSpace(contact.PostalAddress.Country))
|
||||
{ cmd.Parameters.AddWithValue("@poAddressCountry", contact.PostalAddress.Country); }
|
||||
else { cmd.Parameters.AddWithValue("@poAddressCountry", DBNull.Value); }
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@poAddressLine1", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressLine2", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressLine3", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressLine4", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressCity", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressRegion", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressPostalCode", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@poAddressCountry", DBNull.Value);
|
||||
}
|
||||
|
||||
int effected = (int)cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
private void CheckList(ref List<Model.Contact.Contact> contactList)
|
||||
{
|
||||
var tempDic = new Dictionary<string, int>();
|
||||
foreach(var item in contactList)
|
||||
{
|
||||
if (tempDic.ContainsKey(item.ContactName))
|
||||
{ throw new Exception("Duplicate contact name in list."); }
|
||||
else { tempDic.Add(item.ContactName, 0); }
|
||||
if (!item.IsValid())
|
||||
{ throw new Exception("Validation check failed: " + item.ValidationResults[0]); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Sale
|
||||
{
|
||||
public class CreateInvoice : Connection
|
||||
{
|
||||
public CreateInvoice(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
public void ByInvoice(Model.Sale.Invoice invoice)
|
||||
{
|
||||
var invoiceList = new List<Model.Sale.Invoice> { invoice };
|
||||
ByInvoiceList(invoiceList);
|
||||
}
|
||||
public void ByInvoiceList(List<Model.Sale.Invoice> invoiceList)
|
||||
{
|
||||
var updateInvoice = new UpdateInvoice(sqlConnectionString);
|
||||
updateInvoice.ByInvoiceList(invoiceList, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Sale
|
||||
{
|
||||
public class InvoiceGet : InvoiceHeaderGet
|
||||
public class ReadInvoice : ReadInvoiceHeader
|
||||
{
|
||||
public InvoiceGet(string sqlConnectionString) : base(sqlConnectionString)
|
||||
public ReadInvoice(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -45,14 +45,15 @@ namespace BealeEngineering.Core.Data.Database.Sale
|
||||
var parameters = new DynamicParameters();
|
||||
string sqlString = @"
|
||||
SELECT SaleInvoice.SaleInvoiceID
|
||||
,SaleInvoice.ContactID
|
||||
,SaleInvoice.SaleInvoiceNumber
|
||||
,SaleInvoice.InvoiceDate
|
||||
,Contact.ContactName
|
||||
,SaleInvoice.DateDue
|
||||
,SaleInvoice.Reference
|
||||
,SaleInvoice.CurrencyCode
|
||||
,SaleInvoice.InvoiceTotal
|
||||
,SaleInvoice.TaxTotal
|
||||
,SaleInvoice.IsCreditNote
|
||||
,SaleInvoiceLine.SaleInvoiceLineID
|
||||
,SaleInvoiceLine.SaleInvoiceID
|
||||
,SaleInvoiceLine.LineNumber
|
||||
@@ -66,6 +67,7 @@ namespace BealeEngineering.Core.Data.Database.Sale
|
||||
,SaleInvoiceLine.TaxAmount
|
||||
,SaleInvoiceLine.LineAmount
|
||||
FROM SaleInvoice
|
||||
INNER JOIN Contact ON SaleInvoice.ContactID = Contact.ContactID
|
||||
LEFT OUTER JOIN SaleInvoiceLine ON SaleInvoice.SaleInvoiceID = SaleInvoiceLine.SaleInvoiceID";
|
||||
|
||||
AddSqlWhereString(ref sqlString, ref parameters);
|
||||
@@ -82,7 +84,7 @@ namespace BealeEngineering.Core.Data.Database.Sale
|
||||
|
||||
var invoiceDictionary = new Dictionary<int, Model.Sale.Invoice>();
|
||||
|
||||
var invoiceList = conn.Query<Model.Sale.Invoice, Model.Sale.InvoiceLine, Model.Sale.Invoice>
|
||||
var invoiceList = conn.Query<Model.Sale.Invoice, Model.Sale.Invoice.InvoiceLine, Model.Sale.Invoice>
|
||||
(
|
||||
sqlString,
|
||||
(invoice, invoiceDetail) =>
|
||||
@@ -92,7 +94,7 @@ namespace BealeEngineering.Core.Data.Database.Sale
|
||||
if (!invoiceDictionary.TryGetValue(invoice.SaleInvoiceID, out invoiceEntry))
|
||||
{
|
||||
invoiceEntry = invoice;
|
||||
invoiceEntry.InvoiceLineList = new List<Model.Sale.InvoiceLine>();
|
||||
invoiceEntry.InvoiceLineList = new List<Model.Sale.Invoice.InvoiceLine>();
|
||||
invoiceDictionary.Add(invoiceEntry.SaleInvoiceID, invoiceEntry);
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Database.Sale
|
||||
{
|
||||
public class InvoiceHeaderGet : Connection
|
||||
public class ReadInvoiceHeader : Connection
|
||||
{
|
||||
public InvoiceHeaderGet(string sqlConnectionString) : base(sqlConnectionString)
|
||||
public ReadInvoiceHeader(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -130,17 +130,18 @@ namespace BealeEngineering.Core.Data.Database.Sale
|
||||
// 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";
|
||||
SELECT SaleInvoice.SaleInvoiceID
|
||||
,SaleInvoice.SaleInvoiceNumber
|
||||
,SaleInvoice.InvoiceDate
|
||||
,SaleInvoice.DateDue
|
||||
,SaleInvoice.Reference
|
||||
,SaleInvoice.CurrencyCode
|
||||
,SaleInvoice.InvoiceTotal
|
||||
,SaleInvoice.TaxTotal
|
||||
,SaleInvoice.IsCreditNote
|
||||
,Contact.ContactName
|
||||
FROM SaleInvoice
|
||||
INNER JOIN Contact ON SaleInvoice.ContactID = Contact.ContactID";
|
||||
|
||||
AddSqlWhereString(ref sqlString, ref parameters);
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
using Dapper;
|
||||
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.Sale
|
||||
{
|
||||
public class UpdateInvoice : Connection
|
||||
{
|
||||
public UpdateInvoice(string sqlConnectionString) : base(sqlConnectionString)
|
||||
{
|
||||
|
||||
}
|
||||
public void ByInvoice(Model.Sale.Invoice invoice, bool insertNew = false)
|
||||
{
|
||||
var invoiceList = new List<Model.Sale.Invoice> { invoice };
|
||||
ByInvoiceList(invoiceList, insertNew);
|
||||
}
|
||||
public void ByInvoiceList(List<Model.Sale.Invoice> invoiceList, bool insertNew = false)
|
||||
{
|
||||
// check the list
|
||||
CheckList(ref invoiceList);
|
||||
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
// get list of id from db
|
||||
var dic = new Dictionary<string, int>();
|
||||
string sqlString = @"
|
||||
SELECT SaleInvoiceNumber, SaleInvoiceID
|
||||
FROM saleInvoice
|
||||
WHERE SaleInvoiceNumber IN @saleInvoiceNumber;";
|
||||
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("@saleInvoiceNumber", invoiceList.Select(o => o.SaleInvoiceNumber).ToList());
|
||||
using (var reader = conn.ExecuteReader(sqlString, parameters))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
if (!dic.ContainsKey(reader.GetString(0)))
|
||||
{
|
||||
dic.Add(reader.GetString(0), reader.GetInt32(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var invoice in invoiceList)
|
||||
{
|
||||
int saleInvoiceId = 0;
|
||||
if (dic.ContainsKey(invoice.SaleInvoiceNumber))
|
||||
{
|
||||
saleInvoiceId = dic[invoice.SaleInvoiceNumber];
|
||||
sqlString = @"
|
||||
UPDATE SaleInvoice
|
||||
SET
|
||||
[ContactID] = (SELECT ContactID FROM Contact WHERE ContactName = @contactName)
|
||||
,[SaleInvoiceNumber] = @saleInvoiceNumber
|
||||
,[InvoiceDate] = @invoiceDate
|
||||
,[DateDue] = @dateDue
|
||||
,[Reference] = @reference
|
||||
,[CurrencyCode] = @currencyCode
|
||||
,[InvoiceTotal] = @invoiceTotal
|
||||
,[TaxTotal] = @taxTotal
|
||||
,[IsCreditNote] = @isCreditNote
|
||||
WHERE SaleInvoiceID = @saleInvoiceId;
|
||||
|
||||
DELETE FROM SaleInvoiceLine WHERE SaleInvoiceID = @saleInvoiceId;";
|
||||
}
|
||||
else if (insertNew)
|
||||
{
|
||||
sqlString = @"
|
||||
INSERT INTO SaleInvoice(
|
||||
[ContactID]
|
||||
,[SaleInvoiceNumber]
|
||||
,[InvoiceDate]
|
||||
,[DateDue]
|
||||
,[Reference]
|
||||
,[CurrencyCode]
|
||||
,[InvoiceTotal]
|
||||
,[TaxTotal]
|
||||
,[IsCreditNote]
|
||||
)
|
||||
OUTPUT INSERTED.SaleInvoiceID
|
||||
VALUES(
|
||||
(SELECT ContactID FROM Contact WHERE ContactName = @contactName)
|
||||
@saleInvoiceNumber
|
||||
@invoiceDate
|
||||
@dateDue
|
||||
@reference
|
||||
@currencyCode
|
||||
@invoiceTotal
|
||||
@taxTotal
|
||||
@isCreditNote
|
||||
)";
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@contactName", invoice.ContactName);
|
||||
cmd.Parameters.AddWithValue("@saleInvoiceNumber", invoice.SaleInvoiceNumber);
|
||||
cmd.Parameters.AddWithValue("@invoiceDate", invoice.InvoiceDate);
|
||||
if (invoice.DueDate == null) { cmd.Parameters.AddWithValue("@dateDue", DBNull.Value); }
|
||||
else { cmd.Parameters.AddWithValue("@dateDue", invoice.DueDate); }
|
||||
cmd.Parameters.AddWithValue("@reference", invoice.Reference);
|
||||
cmd.Parameters.AddWithValue("@currencyCode", invoice.CurrencyCode);
|
||||
cmd.Parameters.AddWithValue("@invoiceTotal", invoice.InvoiceTotal);
|
||||
cmd.Parameters.AddWithValue("@taxTotal", invoice.TaxTotal);
|
||||
cmd.Parameters.AddWithValue("@isCreditNote", invoice.IsCreditNote);
|
||||
|
||||
if (saleInvoiceId == 0)
|
||||
{
|
||||
saleInvoiceId = (int)cmd.ExecuteScalar();
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@saleInvoiceId", saleInvoiceId);
|
||||
int effected = cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
// deal with lines
|
||||
foreach (var line in invoice.InvoiceLineList)
|
||||
{
|
||||
sqlString = @"
|
||||
INSERT INTO SaleInvoiceLine(
|
||||
[SaleInvoiceID]
|
||||
,[LineNumber]
|
||||
,[InventoryItemCode]
|
||||
,[Description]
|
||||
,[Quantity]
|
||||
,[UnitAmount]
|
||||
,[Discount]
|
||||
,[AccountCode]
|
||||
,[TaxType]
|
||||
,[TaxAmount]
|
||||
,[LineAmount]
|
||||
)
|
||||
VALUES(
|
||||
@saleInvoiceID
|
||||
,@lineNumber
|
||||
,@inventoryItemCode
|
||||
,@description
|
||||
,@quantity
|
||||
,@unitAmount
|
||||
,@discount
|
||||
,@accountCode
|
||||
,@taxType
|
||||
,@taxAmount
|
||||
,@lineAmount
|
||||
)";
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@saleInvoiceID", saleInvoiceId);
|
||||
cmd.Parameters.AddWithValue("@lineNumber", line.LineNumber);
|
||||
if (string.IsNullOrWhiteSpace(line.InventoryItemCode)) { cmd.Parameters.AddWithValue("@inventoryItemCode", DBNull.Value); }
|
||||
else { cmd.Parameters.AddWithValue("@inventoryItemCode", line.InventoryItemCode); }
|
||||
if (string.IsNullOrWhiteSpace(line.Description)) { cmd.Parameters.AddWithValue("@description", DBNull.Value); }
|
||||
else { cmd.Parameters.AddWithValue("@description", line.Description); }
|
||||
cmd.Parameters.AddWithValue("@quantity", line.Quantity);
|
||||
cmd.Parameters.AddWithValue("@unitAmount", line.UnitAmount);
|
||||
if (line.Discount == null) { cmd.Parameters.AddWithValue("@discount", DBNull.Value); }
|
||||
else { cmd.Parameters.AddWithValue("@discount", line.Discount); }
|
||||
if (string.IsNullOrWhiteSpace(line.AccountCode)) { cmd.Parameters.AddWithValue("@accountCode", DBNull.Value); }
|
||||
else { cmd.Parameters.AddWithValue("@accountCode", line.AccountCode); }
|
||||
if (string.IsNullOrWhiteSpace(line.TaxType)) { cmd.Parameters.AddWithValue("@taxType", DBNull.Value); }
|
||||
else { cmd.Parameters.AddWithValue("@taxType", line.TaxType); }
|
||||
cmd.Parameters.AddWithValue("@taxAmount", line.TaxAmount);
|
||||
cmd.Parameters.AddWithValue("@lineAmount", line.LineAmount);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
private void CheckList(ref List<Model.Sale.Invoice> invoiceList)
|
||||
{
|
||||
var tempDic = new Dictionary<string, int>();
|
||||
foreach (var item in invoiceList)
|
||||
{
|
||||
if (tempDic.ContainsKey(item.SaleInvoiceNumber))
|
||||
{ throw new Exception("Duplicate contact name in list."); }
|
||||
else { tempDic.Add(item.SaleInvoiceNumber, 0); }
|
||||
if (!item.IsValid())
|
||||
{ throw new Exception("Validation check failed: " + item.ValidationResults[0]); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Data.Xero.FlatFile
|
||||
{
|
||||
public class ImportInvoice
|
||||
public class ReadXeroInvoiceFlatFile
|
||||
{
|
||||
public ImportInvoice()
|
||||
public ReadXeroInvoiceFlatFile()
|
||||
{
|
||||
FileInputPath =
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
|
||||
@@ -31,7 +31,7 @@ namespace BealeEngineering.Core.Data.Xero.FlatFile
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns>Dictionary, Invoice numbers against data.</returns>
|
||||
public Dictionary<string, Model.Import.XeroInvoiceFlatFile> ByFilePath(string filePath)
|
||||
public List<Model.Import.XeroInvoiceFlatFile> ByFilePath(string filePath)
|
||||
{
|
||||
/* So here's the rub. Any field in a CSV doc that has a double quote wihtin, must be enclosed by double quotes and
|
||||
* the double quote within must be 'escaped' by a double quote.
|
||||
@@ -64,7 +64,7 @@ namespace BealeEngineering.Core.Data.Xero.FlatFile
|
||||
dto = csv.GetRecords<Model.Import.XeroInvoiceFlatFileDTO>().ToList();
|
||||
}
|
||||
|
||||
return ConvertFlatDTO(ref dto);
|
||||
return ConvertFlatDTO(ref dto).Values.ToList();
|
||||
}
|
||||
|
||||
private Dictionary<string, Model.Import.XeroInvoiceFlatFile> ConvertFlatDTO(ref List<Model.Import.XeroInvoiceFlatFileDTO> flatData)
|
||||
@@ -27,7 +27,7 @@ namespace BealeEngineering.Core.Logic.Client
|
||||
Init();
|
||||
|
||||
// get list of unallocated invoices
|
||||
var poAlloInstance = new Data.Database.Client.PurchaseOrderAllocationGet(SqlConnectionString);
|
||||
var poAlloInstance = new Data.Database.Client.ReadPurchaseOrderAllocation(SqlConnectionString);
|
||||
var invoiceIdList = poAlloInstance.GetUnallocatedInvoiceId();
|
||||
|
||||
// nothing to allocate
|
||||
@@ -42,7 +42,7 @@ namespace BealeEngineering.Core.Logic.Client
|
||||
}
|
||||
|
||||
// get invoice header info
|
||||
var invoiceInst = new Data.Database.Sale.InvoiceHeaderGet(SqlConnectionString);
|
||||
var invoiceInst = new Data.Database.Sale.ReadInvoiceHeader(SqlConnectionString);
|
||||
var invoiceList = invoiceInst.GetBySaleInvoiceId(invoiceIdList);
|
||||
|
||||
// create lookup list for matching
|
||||
@@ -72,7 +72,7 @@ namespace BealeEngineering.Core.Logic.Client
|
||||
//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);
|
||||
var poInstance = new Data.Database.Client.ReadPurchaseOrder(SqlConnectionString);
|
||||
poInstance.Reference = referenceList.Distinct().ToList();
|
||||
poInstance.ReturnIsClosed = true; // <--------------------------------------------------change to false after
|
||||
var clientPoList = poInstance.GetByFilters();
|
||||
@@ -90,7 +90,7 @@ namespace BealeEngineering.Core.Logic.Client
|
||||
// match contact ID
|
||||
foreach (var po in clientPoList)
|
||||
{
|
||||
if (po.ContactID == lookupList[i].Item1.ContactID)
|
||||
if (po.Contact.ContactName == lookupList[i].Item1.ContactName)
|
||||
{
|
||||
// match PO reference
|
||||
string reference = lookupList[i].Item2;
|
||||
@@ -143,7 +143,7 @@ namespace BealeEngineering.Core.Logic.Client
|
||||
// update db table
|
||||
if (invoiceIdToPoLineId.Count > 0)
|
||||
{
|
||||
var instance2 = new Data.Database.Client.PurchaseOrderAllocationCreate(SqlConnectionString);
|
||||
var instance2 = new Data.Database.Client.CreatePurchaseOrderAllocation(SqlConnectionString);
|
||||
InvoiceMatched = instance2.ByDictionary(invoiceIdToPoLineId);
|
||||
}
|
||||
IsComplete = true;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
using CsvHelper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualBasic.FileIO;
|
||||
|
||||
namespace BealeEngineering.Core.Logic.Import
|
||||
{
|
||||
public class XeroInvoiceFlatFile
|
||||
{
|
||||
private List<Model.Import.XeroInvoiceFlatFile> XeroInvoiceData { get; set; }
|
||||
private List<Model.Sale.Invoice> DbInvoiceData { get; set; }
|
||||
public XeroInvoiceFlatFile(string sqlConnectionString)
|
||||
{
|
||||
SqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
private string SqlConnectionString { get; set; }
|
||||
public void ByFilePath(string filePath, bool updateContacts = true)
|
||||
{
|
||||
// get xero data
|
||||
var data = new Data.Xero.FlatFile.ReadXeroInvoiceFlatFile();
|
||||
XeroInvoiceData = data.ByFilePath(filePath);
|
||||
|
||||
// update db contacts
|
||||
UpdateContacts();
|
||||
|
||||
// populate/map xero data to invoice model list
|
||||
MapInvoiceDetails();
|
||||
|
||||
//check
|
||||
if (XeroInvoiceData.Count != DbInvoiceData.Count)
|
||||
{
|
||||
throw new Exception("Something went wrong while mapping the data.");
|
||||
}
|
||||
|
||||
// send list to database (it will get validated in data layer)
|
||||
if (DbInvoiceData.Any())
|
||||
{
|
||||
var updateInvoice = new Data.Database.Sale.UpdateInvoice(SqlConnectionString);
|
||||
updateInvoice.ByInvoiceList(DbInvoiceData);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a dictionary of contacts, referenced by unique 'Contact Name'. Any contacts not found in db are
|
||||
/// automatically added.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private void UpdateContacts()
|
||||
{
|
||||
var dicContacts = new Dictionary<string, Model.Contact.Contact>();
|
||||
for (var i = 0; i < XeroInvoiceData.Count; i++)
|
||||
{
|
||||
if (!dicContacts.ContainsKey(XeroInvoiceData[0].ContactName))
|
||||
{
|
||||
dicContacts.Add(XeroInvoiceData[0].ContactName, MapContactDetails(XeroInvoiceData[0]));
|
||||
}
|
||||
}
|
||||
if (dicContacts.Any())
|
||||
{
|
||||
var updateContact = new Data.Database.Contact.UpdateContact(SqlConnectionString);
|
||||
updateContact.ByContactList(dicContacts.Values.ToList());
|
||||
}
|
||||
}
|
||||
private Model.Contact.Contact MapContactDetails(Model.Import.XeroInvoiceFlatFile xeroData)
|
||||
{
|
||||
var contact = new Model.Contact.Contact();
|
||||
contact.ContactName = xeroData.ContactName;
|
||||
if (string.IsNullOrWhiteSpace(xeroData.EmailAddress)) { contact.EmailAddress = null; }
|
||||
else { contact.EmailAddress = xeroData.EmailAddress; }
|
||||
|
||||
var address = new Model.Contact.Address();
|
||||
address.AddressLine1 = xeroData.POAddressLine1;
|
||||
address.AddressLine2 = xeroData.POAddressLine2;
|
||||
address.AddressLine3 = xeroData.POAddressLine3;
|
||||
address.AddressLine4 = xeroData.POAddressLine4;
|
||||
address.City = xeroData.POCity;
|
||||
address.Country = xeroData.POCountry;
|
||||
address.PostalCode = xeroData.POPostalCode;
|
||||
address.Region = xeroData.PORegion;
|
||||
|
||||
if (address.IsValid()) { contact.PostalAddress = address; }
|
||||
|
||||
return contact;
|
||||
}
|
||||
private void MapInvoiceDetails()
|
||||
{
|
||||
DbInvoiceData = new List<Model.Sale.Invoice>();
|
||||
for (var i = 0; i < XeroInvoiceData.Count; i++)
|
||||
{
|
||||
if (XeroInvoiceData[i] == null) { throw new NullReferenceException(); }
|
||||
var invoice = new Model.Sale.Invoice();
|
||||
|
||||
invoice.ContactName = XeroInvoiceData[i].ContactName;
|
||||
invoice.CurrencyCode = XeroInvoiceData[i].Currency;
|
||||
invoice.DueDate = XeroInvoiceData[i].DueDate;
|
||||
invoice.InvoiceDate = XeroInvoiceData[i].InvoiceDate;
|
||||
invoice.InvoiceTotal = XeroInvoiceData[i].Total;
|
||||
if (XeroInvoiceData[i].Type == "Sales invoice") { invoice.IsCreditNote = false; }
|
||||
else if (XeroInvoiceData[i].Type == "Sales credit note") { invoice.IsCreditNote = true; }
|
||||
else { throw new FormatException("Unknow value '" + XeroInvoiceData[i].Type + "' found in 'Type' field"); }
|
||||
invoice.Reference = XeroInvoiceData[i].Reference;
|
||||
invoice.SaleInvoiceNumber = XeroInvoiceData[i].InvoiceNumber;
|
||||
invoice.TaxTotal = XeroInvoiceData[i].TaxTotal;
|
||||
|
||||
invoice.InvoiceLineList = new List<Model.Sale.Invoice.InvoiceLine>();
|
||||
for (int j = 0; j < XeroInvoiceData[i].LineItems.Count; j++)
|
||||
{
|
||||
if (XeroInvoiceData[i].LineItems[j] == null) { throw new NullReferenceException(); }
|
||||
var invoiceLine = new Model.Sale.Invoice.InvoiceLine();
|
||||
|
||||
invoiceLine.LineNumber = j + 1;
|
||||
invoiceLine.AccountCode = XeroInvoiceData[i].LineItems[j].AccountCode;
|
||||
invoiceLine.Description = XeroInvoiceData[i].LineItems[j].Description;
|
||||
invoiceLine.Discount = XeroInvoiceData[i].LineItems[j].Discount;
|
||||
invoiceLine.InventoryItemCode = XeroInvoiceData[i].LineItems[j].InventoryItemCode;
|
||||
invoiceLine.Quantity = XeroInvoiceData[i].LineItems[j].Quantity;
|
||||
invoiceLine.TaxAmount = XeroInvoiceData[i].LineItems[j].TaxAmount;
|
||||
invoiceLine.TaxType = XeroInvoiceData[i].LineItems[j].TaxType;
|
||||
invoiceLine.UnitAmount = XeroInvoiceData[i].LineItems[j].UnitAmount;
|
||||
|
||||
//check, as line amount is same as calculated in model
|
||||
if (invoiceLine.LineAmount != XeroInvoiceData[i].LineItems[j].LineAmount)
|
||||
{
|
||||
throw new Exception("Imported line total does not equal caluclated.");
|
||||
}
|
||||
invoice.InvoiceLineList.Add(invoiceLine);
|
||||
}
|
||||
DbInvoiceData.Add(invoice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using CsvHelper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualBasic.FileIO;
|
||||
|
||||
namespace BealeEngineering.Core.Logic.Import
|
||||
{
|
||||
public class wipXeroInvoiceFlatFile
|
||||
{
|
||||
public wipXeroInvoiceFlatFile(string sqlConnectionString)
|
||||
{
|
||||
SqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
private string SqlConnectionString { get; set; }
|
||||
public void ByFilePath(string filePath)
|
||||
{
|
||||
// get model list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// get db invoices
|
||||
//var saleInvInst = new Data.Database.Sale.InvoiceGet(SqlConnectionString);
|
||||
//saleInvInst.InvoiceNumber = invDictionary.Keys.ToList();
|
||||
//var dataInvList = saleInvInst.GetByFilters();
|
||||
|
||||
// compare
|
||||
|
||||
|
||||
// update modified records
|
||||
|
||||
// insert new records <--------- only insert approved invoices
|
||||
|
||||
// delete records (is this possible??) <------- i think so, include deleted and voided in flatfile??
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,15 @@ namespace BealeEngineering.Core.Model.Client
|
||||
else { return OrderLineList.Count; }
|
||||
}
|
||||
}
|
||||
public List<Client.PurchaseOrderLine> OrderLineList { get; set; }
|
||||
public List<PurchaseOrderLine> OrderLineList { get; set; }
|
||||
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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,28 +11,10 @@ namespace BealeEngineering.Core.Model.Client
|
||||
{
|
||||
public int ClientPurchaseOrderID { get; set; }
|
||||
public DateTime PurchaseOrderDate { get; set; }
|
||||
public int ContactID { get; set; }
|
||||
public Model.Contact.Contact Contact { 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;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Model.Contact
|
||||
{
|
||||
public class Address : ValidateModel
|
||||
{
|
||||
[Required(AllowEmptyStrings = false), StringLength(100)]
|
||||
public string AddressLine1 { get; set; }
|
||||
[StringLength(100)]
|
||||
public string AddressLine2 { get; set; }
|
||||
[StringLength(100)]
|
||||
public string AddressLine3 { get; set; }
|
||||
[StringLength(100)]
|
||||
public string AddressLine4 { get; set; }
|
||||
[Required(AllowEmptyStrings = false), StringLength(100)]
|
||||
public string City { get; set; }
|
||||
[StringLength(100)]
|
||||
public string Region { get; set; }
|
||||
[Required(AllowEmptyStrings = false), StringLength(50)]
|
||||
public string PostalCode { get; set; }
|
||||
[StringLength(100)]
|
||||
public string Country { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Model.Contact
|
||||
{
|
||||
public class Contact : ValidateModel
|
||||
{
|
||||
public int ContactId { get; set; }
|
||||
[Required(AllowEmptyStrings = false), StringLength(100)]
|
||||
public string ContactName { get; set; }
|
||||
[StringLength(150), EmailAddress]
|
||||
public string EmailAddress { get; set; }
|
||||
public string PrimaryPersonFirstName { get; set; }
|
||||
public string PrimaryPersonSurname { get; set; }
|
||||
public string PrimaryPersonEmail { get; set; }
|
||||
public Address PostalAddress { get; set; }
|
||||
public bool PostalAddressIsSet
|
||||
{
|
||||
get
|
||||
{
|
||||
if(PostalAddress == null) { return false; }
|
||||
else { return true; }
|
||||
}
|
||||
}
|
||||
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (ValidationResults == null) { ValidationResults = new List<ValidationResult>(); }
|
||||
if (PostalAddressIsSet)
|
||||
{
|
||||
//var lkdfj = Validator.TryValidateObject(this.PostalAddress,
|
||||
//new ValidationContext(this.PostalAddress, null, null) { MemberName = "PostalAddress" },
|
||||
//ValidationResults);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// this doesn't
|
||||
//Contact contact = validationContext as contact;
|
||||
//if (contact != null)
|
||||
//{
|
||||
// // ValidationResult(" Error Message ", " MemberNames " )
|
||||
// yield return new ValidationResult("No Department and Employees information", new string[] { "DepartmentList & EmployeeList" });
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
//// this works!!!!!!!!!!
|
||||
var context = new ValidationContext(this.PostalAddress);
|
||||
var results = new List<ValidationResult>();
|
||||
if (!Validator.TryValidateObject(this.PostalAddress, context, results))
|
||||
{
|
||||
ValidationResults.AddRange(results);
|
||||
}
|
||||
|
||||
|
||||
//if (!PostalAddress.IsValid())
|
||||
//{
|
||||
|
||||
// // for some reason, when an invalid property is found, it is
|
||||
// // added to the list twice.
|
||||
// // It works, so no point in trying to fix
|
||||
// ValidationResults.AddRange(PostalAddress.ValidationResults);
|
||||
//}
|
||||
}
|
||||
|
||||
return ValidationResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@@ -8,6 +9,87 @@ namespace BealeEngineering.Core.Model.Sale
|
||||
{
|
||||
public class Invoice : InvoiceHeader
|
||||
{
|
||||
public List<Model.Sale.InvoiceLine> InvoiceLineList { get; set; }
|
||||
public List<InvoiceLine> InvoiceLineList { get; set; } = new List<InvoiceLine>();
|
||||
public bool InvoiceLineListIsSet
|
||||
{
|
||||
get
|
||||
{
|
||||
if (InvoiceLineList == null || !InvoiceLineList.Any()) { return false; }
|
||||
else { return true; }
|
||||
}
|
||||
}
|
||||
public class InvoiceLine
|
||||
{
|
||||
[Required(), Range(0, 255)]
|
||||
public int LineNumber { get; set; }
|
||||
[Required(), StringLength(50)]
|
||||
public string InventoryItemCode { get; set; }
|
||||
[StringLength(500)]
|
||||
public string Description { get; set; }
|
||||
[Required(), Range(0, 255)]
|
||||
public decimal Quantity { get; set; }
|
||||
[Required()]
|
||||
public decimal UnitAmount { get; set; }
|
||||
[Range(1, 100)]
|
||||
public int? Discount { get; set; }
|
||||
[Required(), StringLength(10)]
|
||||
public string AccountCode { get; set; }
|
||||
[Required(), StringLength(50)]
|
||||
public string TaxType { get; set; }
|
||||
[Required()]
|
||||
public decimal TaxAmount { get; set; }
|
||||
/// <summary>
|
||||
/// Line amount is Tax Exclusive
|
||||
/// </summary>
|
||||
public decimal LineAmount
|
||||
{
|
||||
get
|
||||
{
|
||||
int discount;
|
||||
if (Discount == null || Discount == 0) { discount = 100; }
|
||||
else { discount = (int)Discount; }
|
||||
return decimal.Round(((Quantity * UnitAmount) * (discount / 100m)),2, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
base.Validate(validationContext);
|
||||
|
||||
// additional validation
|
||||
if (!InvoiceLineListIsSet)
|
||||
{
|
||||
var result = new ValidationResult("Invoice must have at least one line.");
|
||||
ValidationResults.Add(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
decimal lineTotal = 0;
|
||||
decimal lineTaxTotal = 0;
|
||||
foreach (var line in InvoiceLineList)
|
||||
{
|
||||
// checks on each line
|
||||
if (line.Quantity <= 0)
|
||||
{
|
||||
var result = new ValidationResult("Quantity must be greater than zero.");
|
||||
ValidationResults.Add(result);
|
||||
}
|
||||
|
||||
lineTotal = lineTotal + line.LineAmount ;
|
||||
lineTaxTotal = lineTaxTotal + line.TaxAmount;
|
||||
}
|
||||
if (lineTotal + lineTaxTotal != InvoiceTotal)
|
||||
{
|
||||
var result = new ValidationResult("Line total is not equal to Invoice Total.");
|
||||
ValidationResults.Add(result);
|
||||
}
|
||||
if (lineTaxTotal != TaxTotal)
|
||||
{
|
||||
var result = new ValidationResult("Line tax total is not equal to Invoice Tax Total.");
|
||||
ValidationResults.Add(result);
|
||||
}
|
||||
}
|
||||
return ValidationResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Model.Sale
|
||||
{
|
||||
public class InvoiceHeader
|
||||
public class InvoiceHeader : ValidateModel
|
||||
{
|
||||
public int SaleInvoiceID { get; set; }
|
||||
public int ContactID { get; set; }
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string ContactName { get; set; }
|
||||
[Required(AllowEmptyStrings = false), StringLength(50)]
|
||||
public string SaleInvoiceNumber { get; set; }
|
||||
[Required()]
|
||||
public DateTime InvoiceDate { get; set; }
|
||||
public DateTime DueDate { get; set; }
|
||||
public DateTime? DueDate { get; set; }
|
||||
[StringLength(50)]
|
||||
public string Reference { get; set; }
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
[StringLength(3, MinimumLength = 3)]
|
||||
public string CurrencyCode { get; set; }
|
||||
[Required()]
|
||||
public decimal InvoiceTotal { get; set;}
|
||||
[Required()]
|
||||
public decimal TaxTotal { get; set; }
|
||||
[Required()]
|
||||
public bool IsCreditNote { get; set; }
|
||||
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
base.Validate(validationContext);
|
||||
|
||||
if (IsCreditNote && InvoiceTotal > 0)
|
||||
{
|
||||
var result = new ValidationResult("Credit note total cannot be greater than zero.");
|
||||
ValidationResults.Add(result);
|
||||
}
|
||||
if (!IsCreditNote && InvoiceTotal < 0)
|
||||
{
|
||||
var result = new ValidationResult("Invoice total cannot be less than zero.");
|
||||
ValidationResults.Add(result);
|
||||
}
|
||||
return ValidationResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Model
|
||||
{
|
||||
public abstract class ValidateModel : IValidatableObject
|
||||
{
|
||||
public List<ValidationResult> ValidationResults { get; protected set; }
|
||||
public bool IsValid()
|
||||
{
|
||||
ValidationResults = new List<ValidationResult>();
|
||||
var validationContext = new ValidationContext(this);
|
||||
if (Validator.TryValidateObject(validationContext.ObjectInstance, validationContext, ValidationResults, true))
|
||||
{ return true; }
|
||||
else
|
||||
{ return false; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Standard checks on class properties. Use 'override' if you wish to add additional checks in a derived classes
|
||||
/// </summary>
|
||||
/// <param name="validationContext"></param>
|
||||
/// <returns>List<ValidationResult></returns>
|
||||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (ValidationResults == null) { ValidationResults = new List<ValidationResult>(); }
|
||||
return ValidationResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,21 +11,28 @@ namespace BealeEngineering.Core.Test
|
||||
public Autoexec(string sqlConnectionString)
|
||||
{
|
||||
SqlConnectionString = sqlConnectionString;
|
||||
|
||||
// enter method to start here
|
||||
Import();
|
||||
}
|
||||
private string SqlConnectionString { get; set; }
|
||||
|
||||
public void Start()
|
||||
public void Invoice()
|
||||
{
|
||||
// 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();
|
||||
|
||||
var inst3 = new Test.Import.ImportFlatfile();
|
||||
inst3.Go();
|
||||
var inst = new Core.Test.Sales.Invoice(SqlConnectionString);
|
||||
}
|
||||
public void Contact()
|
||||
{
|
||||
var inst = new Test.Contact.Contact(SqlConnectionString);
|
||||
}
|
||||
public void Import()
|
||||
{
|
||||
var inst = new Test.Import.ImportFlatfile(SqlConnectionString);
|
||||
}
|
||||
public void ValidateModel()
|
||||
{
|
||||
var inst = new Test.Sales.Invoice(SqlConnectionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace BealeEngineering.Core.Test.Client
|
||||
}
|
||||
public void GetPurchaseOrderById()
|
||||
{
|
||||
var inst = new Core.Data.Database.Client.PurchaseOrderGet(SqlConnectionString);
|
||||
var inst = new Core.Data.Database.Client.ReadPurchaseOrder(SqlConnectionString);
|
||||
var newList = inst.GetByClientPurchaseOrderId(PurchaseOrderIdList);
|
||||
}
|
||||
public void AllocateInvoicesToPurchaseOrders()
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BealeEngineering.Core.Test.Contact
|
||||
{
|
||||
public class Contact
|
||||
{
|
||||
public Contact(string sqlConnectionString)
|
||||
{
|
||||
SqlConnectionString = sqlConnectionString;
|
||||
|
||||
ContactIdList = new List<int>
|
||||
{
|
||||
23, 18, 5
|
||||
};
|
||||
|
||||
EmailAddressList = new List<string>
|
||||
{
|
||||
"phil.kennerley@gardiners.uk.com",
|
||||
"patricia.snook@severntrent.co.uk",
|
||||
"david.lane@severntrent.co.uk"
|
||||
};
|
||||
|
||||
// put method to run here
|
||||
ValidateContact();
|
||||
|
||||
}
|
||||
private string SqlConnectionString { get; set; }
|
||||
public List<int> ContactIdList { get; set; }
|
||||
public List<string> EmailAddressList { get; set; }
|
||||
|
||||
public void ReadContactHeader()
|
||||
{
|
||||
var inst = new Data.Database.Contact.ReadContact(SqlConnectionString);
|
||||
//var result = inst.ByContactId(ContactIdList);
|
||||
//var result = inst.ByEmailAddress(EmailAddressList);
|
||||
}
|
||||
public void ValidateContact()
|
||||
{
|
||||
var inst = new Data.Database.Contact.ReadContact(SqlConnectionString);
|
||||
var result = inst.ByContactName("Ben Broughton");
|
||||
result.PostalAddress.AddressLine1 = " ";
|
||||
bool isValid = result.IsValid();
|
||||
var errorList = result.ValidationResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,23 @@ namespace BealeEngineering.Core.Test.Import
|
||||
{
|
||||
public class ImportFlatfile
|
||||
{
|
||||
public void Go()
|
||||
public ImportFlatfile(string sqlConnectionString)
|
||||
{
|
||||
Go(sqlConnectionString);
|
||||
}
|
||||
public void Go(string sqlConnectionString)
|
||||
{
|
||||
string fileInputPath =
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
|
||||
+ @"\Dropbox\Beale Engineering Services Ltd\BE Accounts\Xero-Export-Invoices.csv";
|
||||
|
||||
var inst = new Data.Xero.FlatFile.ImportInvoice();
|
||||
var lkdsjflsd = inst.ByFilePath(fileInputPath);
|
||||
var inst = new Logic.Import.XeroInvoiceFlatFile(sqlConnectionString);
|
||||
inst.ByFilePath(fileInputPath);
|
||||
|
||||
return;
|
||||
|
||||
var inst2 = new Data.Xero.FlatFile.ReadXeroInvoiceFlatFile();
|
||||
var lkdsjflsd = inst2.ByFilePath(fileInputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BealeEngineering.Core.Test.Sales
|
||||
{
|
||||
@@ -12,14 +13,34 @@ namespace BealeEngineering.Core.Test.Sales
|
||||
{
|
||||
SqlConnectionString = sqlConnectionString;
|
||||
SaleInvoiceIdList = new List<int> { 131, 481, 105, 324 };
|
||||
|
||||
|
||||
// add method you want to start here
|
||||
ValidateInvoice();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
public Model.Sale.InvoiceHeader InvoiceHeader {get; set;}
|
||||
private string SqlConnectionString { get; set; }
|
||||
public List<int> SaleInvoiceIdList { get; set; }
|
||||
|
||||
public void GetInvoice()
|
||||
{
|
||||
var InvInst = new Data.Database.Sale.InvoiceGet(SqlConnectionString);
|
||||
var InvInst = new Data.Database.Sale.ReadInvoice(SqlConnectionString);
|
||||
var lkdjflsk = InvInst.GetBySaleInvoiceId(SaleInvoiceIdList);
|
||||
}
|
||||
public void ValidateInvoice()
|
||||
{
|
||||
var readContact = new Data.Database.Contact.ReadContact(SqlConnectionString);
|
||||
var contact = readContact.ByContactId(1);
|
||||
|
||||
var readInvoice = new Data.Database.Sale.ReadInvoice(SqlConnectionString);
|
||||
var invoices = readInvoice.GetBySaleInvoiceId(new List<int> { 1 });
|
||||
invoices[0].CurrencyCode = "EURR";
|
||||
bool isValid = invoices[0].IsValid();
|
||||
var errorList = invoices[0].ValidationResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user