diff --git a/TechTest/AnyCompany.Tests/AnyCompany.Tests.csproj b/TechTest/AnyCompany.Tests/AnyCompany.Tests.csproj
index b537fc2..dbb2f7b 100644
--- a/TechTest/AnyCompany.Tests/AnyCompany.Tests.csproj
+++ b/TechTest/AnyCompany.Tests/AnyCompany.Tests.csproj
@@ -1,16 +1,28 @@
-
-
+
+
+
+
+
+
Debug
AnyCPU
- cd5d577e-bdc9-4dfc-ac6a-b1da474995f3
+ {60CFE149-CB3F-4227-8EAD-4E16C0796535}
Library
Properties
AnyCompany.Tests
AnyCompany.Tests
- v4.6.1
+ v4.7.2
512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 15.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
true
@@ -30,24 +42,176 @@
4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll
+
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll
+
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.1\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+ ..\packages\Microsoft.Bcl.HashCode.1.1.0\lib\net461\Microsoft.Bcl.HashCode.dll
+
+
+ ..\packages\Microsoft.Data.Sqlite.Core.3.1.6\lib\netstandard2.0\Microsoft.Data.Sqlite.dll
+
+
+ ..\packages\Microsoft.DotNet.PlatformAbstractions.3.1.6\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Abstractions.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.InMemory.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.InMemory.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.Relational.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.Sqlite.Core.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll
+
+
+ ..\packages\Microsoft.Extensions.Caching.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Caching.Memory.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll
+
+
+ ..\packages\Microsoft.Extensions.Configuration.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll
+
+
+ ..\packages\Microsoft.Extensions.Configuration.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Configuration.Binder.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.3.1.6\lib\net461\Microsoft.Extensions.DependencyInjection.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyModel.3.1.6\lib\net451\Microsoft.Extensions.DependencyModel.dll
+
+
+ ..\packages\Microsoft.Extensions.Logging.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Logging.dll
+
+
+ ..\packages\Microsoft.Extensions.Logging.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Options.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Options.dll
+
+
+ ..\packages\Microsoft.Extensions.Primitives.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll
+
+
+ ..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
+
+
+ ..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
+
+
+ ..\packages\Moq.4.14.5\lib\net45\Moq.dll
+
+
+ ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll
+
+
+ ..\packages\SQLitePCLRaw.bundle_e_sqlite3.2.0.2\lib\net461\SQLitePCLRaw.batteries_v2.dll
+
+
+ ..\packages\SQLitePCLRaw.core.2.0.2\lib\netstandard2.0\SQLitePCLRaw.core.dll
+
+
+ ..\packages\SQLitePCLRaw.bundle_e_sqlite3.2.0.2\lib\net461\SQLitePCLRaw.nativelibrary.dll
+
+
+ ..\packages\SQLitePCLRaw.provider.dynamic_cdecl.2.0.2\lib\netstandard2.0\SQLitePCLRaw.provider.dynamic_cdecl.dll
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll
+
+
+ ..\packages\System.ComponentModel.Annotations.4.7.0\lib\net461\System.ComponentModel.Annotations.dll
+
+
+
+
+
+
+ ..\packages\System.Diagnostics.DiagnosticSource.4.7.1\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
+ True
+ True
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+ {E882A9A5-1265-4E61-9BBC-9A50989BA147}
+ AnyCompany
+
+
+
+
-
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TechTest/AnyCompany.Tests/Class1.cs b/TechTest/AnyCompany.Tests/Class1.cs
deleted file mode 100644
index 5957505..0000000
--- a/TechTest/AnyCompany.Tests/Class1.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AnyCompany.Tests
-{
- public class Class1
- {
- }
-}
diff --git a/TechTest/AnyCompany.Tests/MockData/InMemoryAnyCompanyContext.cs b/TechTest/AnyCompany.Tests/MockData/InMemoryAnyCompanyContext.cs
new file mode 100644
index 0000000..8a21510
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/MockData/InMemoryAnyCompanyContext.cs
@@ -0,0 +1,14 @@
+
+namespace InvestecUnitTestsTests.MockData
+{
+ using AnyCompany;
+ using AnyCompany.DAL;
+ using Microsoft.EntityFrameworkCore;
+ public class RepoAnyCompanyContext : AnyCompanyContext
+ {
+ public RepoAnyCompanyContext(DbContextOptions option) : base()
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/TechTest/AnyCompany.Tests/Properties/AssemblyInfo.cs b/TechTest/AnyCompany.Tests/Properties/AssemblyInfo.cs
index 726eefa..c2e3ab8 100644
--- a/TechTest/AnyCompany.Tests/Properties/AssemblyInfo.cs
+++ b/TechTest/AnyCompany.Tests/Properties/AssemblyInfo.cs
@@ -1,36 +1,20 @@
-using System.Reflection;
+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("AnyCompany.Tests")]
+[assembly: AssemblyTitle("InvestecUnitTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Investec Bank")]
-[assembly: AssemblyProduct("AnyCompany.Tests")]
-[assembly: AssemblyCopyright("Copyright © Investec Bank 2018")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("InvestecUnitTests")]
+[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("cd5d577e-bdc9-4dfc-ac6a-b1da474995f3")]
+[assembly: Guid("60cfe149-cb3f-4227-8ead-4e16c0796535")]
-// 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")]
diff --git a/TechTest/AnyCompany.Tests/RepositoryTests/CustomerRepositoryTests.cs b/TechTest/AnyCompany.Tests/RepositoryTests/CustomerRepositoryTests.cs
new file mode 100644
index 0000000..40ec0b2
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/RepositoryTests/CustomerRepositoryTests.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data.Common;
+using System.Data.Entity.Migrations;
+using System.Linq;
+using AnyCompany;
+using AnyCompany.BUL.Services;
+using AnyCompany.DAL;
+using AnyCompany.DAL.Repositories;
+using InvestecUnitTestsTests.MockData;
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+using Moq;
+using NUnit.Framework;
+
+namespace InvestecUnitTests
+{
+ [TestFixture]
+ public class CustomerRepositoryTests : TestsBase
+ {
+ [TestCase]
+ public void GIVEN_VALID_CUSTOMERID_RETURN_CUSTOMER()
+ {
+ //Arrange
+ Customer returnedCustomer = null;
+ int customerIdToGet = 1;
+
+ Customers.ToList().ForEach(i => RepoContext.Customers.AddOrUpdate(i));
+ RepoContext.SaveChanges();
+
+ //Act
+ CustomerRepositoryWrapper CustomerWrapper = new CustomerRepositoryWrapper();
+ returnedCustomer = CustomerWrapper.Get(customerIdToGet);
+
+ //Assert
+ Assert.True(returnedCustomer != null);
+ Assert.True(returnedCustomer.CustomerId == customerIdToGet);
+ }
+
+
+ [TestCase]
+ public void GIVEN_NONEXISTENT_CUSTOMERID_RETURN_NULL()
+ {
+ //Arrange
+ Customer returnedCustomer = null;
+ int customerIdToGet = -9999;
+
+ Customers.ToList().ForEach(i => RepoContext.Customers.AddOrUpdate(i));
+ RepoContext.SaveChanges();
+
+ //Act
+ CustomerRepositoryWrapper CustomerWrapper = new CustomerRepositoryWrapper();
+ returnedCustomer = CustomerWrapper.Get(customerIdToGet);
+
+ //Assert
+ Assert.True(returnedCustomer == null);
+ }
+
+ [TestCase]
+ public void RETURN_CUSTOMERS_WITH_LINKED_ORDERS_BY_DEFAULT()
+ {
+ //Arrange
+ CustomersWithOrders.ToList().ForEach(i => RepoContext.Customers.AddOrUpdate(i));
+ RepoContext.SaveChanges();
+
+ //Act
+ CustomerRepositoryWrapper customerWrapper = new CustomerRepositoryWrapper();
+ IEnumerable returnedCustomers = customerWrapper.GetAll();
+ int orderCount = 0;
+ returnedCustomers.ToList().ForEach(customer => orderCount += customer.Orders.Count);
+
+ //Assert
+ Assert.True(orderCount > 0);
+ Assert.True(returnedCustomers.Count() > 0);
+ }
+
+ [TestCase]
+ public void GIVEN_FALSE_ARGUMENT_RETURN_CUSTOMERS_WITHOUT_LINKED_ORDERS()
+ {
+ //Arrange
+ CustomersWithOrders.ToList().ForEach(i => RepoContext.Customers.AddOrUpdate(i));
+ RepoContext.SaveChanges();
+
+ //Act
+ CustomerRepositoryWrapper customerWrapper = new CustomerRepositoryWrapper();
+ IEnumerable returnedCustomers = customerWrapper.GetAll(false);
+ int orderCount = 0;
+ returnedCustomers.ToList().ForEach(customer => orderCount += customer.Orders.Count);
+
+ //Assert
+ Assert.True(orderCount == 0);
+ Assert.True(returnedCustomers.Count() > 0);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany.Tests/RepositoryTests/OrderRepositoryTests.cs b/TechTest/AnyCompany.Tests/RepositoryTests/OrderRepositoryTests.cs
new file mode 100644
index 0000000..ef4e946
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/RepositoryTests/OrderRepositoryTests.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data.Common;
+using System.Linq;
+using AnyCompany;
+using AnyCompany.BUL.Services;
+using AnyCompany.DAL;
+using AnyCompany.DAL.Repositories;
+using InvestecUnitTestsTests.MockData;
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+using Moq;
+using NUnit.Framework;
+
+namespace InvestecUnitTests
+{
+ [TestFixture]
+ public class OrderRepositoryTests : TestsBase
+ {
+ [TestCase]
+ public void GIVEN_VALID_ORDER_RETURN_TRUE()
+ {
+ //Arrange
+
+ //Act
+ OrderRepositoryWrapper orderWrapper = new OrderRepositoryWrapper();
+ bool isSaved = orderWrapper.Save(ValidOrder);
+
+ //Assert
+ Assert.True(isSaved == true);
+ }
+
+
+ [TestCase]
+ public void GIVEN_INVALID_ORDER_RETURN_FALSE()
+ {
+ //Arrange
+
+ //Act
+ OrderRepositoryWrapper orderWrapper = new OrderRepositoryWrapper();
+ bool isSaved = orderWrapper.Save(InValidOrder);
+
+ //Assert
+ Assert.True(isSaved == false);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany.Tests/ServiceTests/CustomerServiceTests.cs b/TechTest/AnyCompany.Tests/ServiceTests/CustomerServiceTests.cs
new file mode 100644
index 0000000..9f99ce1
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/ServiceTests/CustomerServiceTests.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using AnyCompany;
+using AnyCompany.BUL.Helpers;
+using AnyCompany.BUL.Services;
+using AnyCompany.DAL;
+using AnyCompany.DAL.Repositories;
+using Moq;
+using NUnit.Framework;
+
+namespace InvestecUnitTests
+{
+ [TestFixture]
+ public class CustomerServiceTests
+ {
+ private Mock _customerService = new Mock();
+ private CustomerService customerService;
+ private readonly List customers = new List
+ {
+ new Customer
+ {
+ Name = "Mike America", Country = "US", DateOfBirth = DateTime.Parse("1987-06-01"), CustomerId = 1
+ },
+ new Customer
+ {
+ Name = "Jonathan Canada", Country = "CN", DateOfBirth = DateTime.Parse("1925-06-01"), CustomerId = 2
+ },
+ new Customer
+ {
+ Name = "FROM THE UK CHINKU", Country = "UK", DateOfBirth = DateTime.Parse("2001-06-01"), CustomerId = 3
+ }
+ ,
+ new Customer
+ {
+ Name = "Not in Database Adams", Country = "AG", DateOfBirth = DateTime.Parse("1982-12-12"), CustomerId = 50
+ }
+ };
+ private readonly List customersWithOrders = new List
+ {
+ new Customer
+ {
+ Name = "I Have Order too", Country = "NM", DateOfBirth = DateTime.Parse("1987-06-01"), CustomerId = 12
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 500,
+ OrderId = 12,
+ CustomerId = 1,
+ VAT = 15
+ }
+ }
+ },
+ new Customer
+ {
+ Name = "I Have Order", Country = "ZW", DateOfBirth = DateTime.Parse("1925-06-01"), CustomerId = 13
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 500,
+ OrderId = 12,
+ CustomerId = 1,
+ VAT = 15
+ }
+ }
+ }
+ };
+
+ [TestCase]
+ public void GIVEN_EXISTINGId_RETURNS_MATCHING_CUSTOMER()
+ {
+ //Arrange
+ Customer matchingCustomer = customers[2];
+ _customerService.Setup(x => x.Get(matchingCustomer.CustomerId)).Returns(matchingCustomer);
+
+ //Act
+ customerService = new CustomerService(_customerService.Object);
+ Customer returnedCustomer = customerService.RetrieveACustomer(matchingCustomer.CustomerId);
+
+ //Asset
+ Assert.AreSame(returnedCustomer, matchingCustomer);
+ Assert.AreEqual(returnedCustomer.CustomerId, matchingCustomer.CustomerId);
+ }
+
+ [TestCase]
+ public void GIVEN_WRONGId_RETURNS_NONMATCHING_CUSTOMER()
+ {
+ //Arrange
+ Customer customerToGet = customers[2];
+ Customer notMatchingCustomer = customers[0];
+ _customerService.Setup(x => x.Get(customerToGet.CustomerId)).Returns(notMatchingCustomer);
+
+ //Act
+ customerService = new CustomerService(_customerService.Object);
+ Customer returnedCustomer = customerService.RetrieveACustomer(customerToGet.CustomerId);
+
+ //Asset
+ Assert.AreNotSame(returnedCustomer, customerToGet);
+ }
+
+ [TestCase]
+ public void GIVEN_NONEXISTENTId_RETURNS_EMPTYCUSTOMEROBJECT()
+ {
+ //Arrange
+ int NonExtentId = 344;
+
+ _customerService.Setup(x => x.Get(NonExtentId)).Returns(new Customer());
+
+ //Act
+ customerService = new CustomerService(_customerService.Object);
+ Customer returnedCustomer = customerService.RetrieveACustomer(NonExtentId);
+
+ //Asset
+ Assert.True(returnedCustomer.CustomerId == 0);
+ }
+
+ [TestCase]
+ public void GIVEN_TRUE_ARGUMENT_RETURNS_CUSTOMERS_WITH_LINKED_ORDERS()
+ {
+ //Arrange
+ _customerService.Setup(x => x.GetAll(true)).Returns(customersWithOrders);
+
+ //Act
+ customerService = new CustomerService(_customerService.Object);
+ IEnumerable returnedCustomers = customerService.RetrieveCustomers(true);
+ int orderCount = 0;
+ returnedCustomers.ToList().ForEach(i => orderCount += i.Orders.Count);
+
+ //Asset
+ Assert.AreSame(customersWithOrders, returnedCustomers);
+ Assert.True(orderCount > 0);
+ }
+
+ [TestCase]
+ public void GIVEN_FALSE_ARGUMENT_RETURNS_CUSTOMERS_WITHOUT_LINKED_ORDERS()
+ {
+ //Arrange
+ _customerService.Setup(x => x.GetAll(false)).Returns(customers);
+
+ //Act
+ customerService = new CustomerService(_customerService.Object);
+ IEnumerable returnedCustomers = customerService.RetrieveCustomers(false);
+
+ int orderCount = 0;
+ returnedCustomers.ToList().ForEach(customer => orderCount += customer.Orders.Count);
+
+ //Asset
+ Assert.AreEqual(orderCount, 0);
+ Assert.AreNotSame(returnedCustomers, customersWithOrders);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany.Tests/ServiceTests/OrderServiceTests.cs b/TechTest/AnyCompany.Tests/ServiceTests/OrderServiceTests.cs
new file mode 100644
index 0000000..64efe3a
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/ServiceTests/OrderServiceTests.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using AnyCompany;
+using AnyCompany.BUL.Services;
+using AnyCompany.DAL;
+using Moq;
+using NUnit.Framework;
+
+namespace InvestecUnitTests
+{
+ [TestFixture]
+ public class OrderServiceTests
+ {
+ private Mock _orderService = new Mock();
+ private Mock _customerService = new Mock();
+ private OrderService orderService;
+ private List customers = new List
+ {
+ new Customer
+ {
+ Name = "Mike America", Country = "US", DateOfBirth = DateTime.Parse("1987-06-01"), CustomerId = 1
+ },
+ new Customer
+ {
+ Name = "Jonathan Canada", Country = "CN", DateOfBirth = DateTime.Parse("1925-06-01"), CustomerId = 2
+ },
+ new Customer
+ {
+ Name = "FROM THE UK CHINKU", Country = "UK", DateOfBirth = DateTime.Parse("2001-06-01"), CustomerId = 3
+ }
+ ,
+ new Customer
+ {
+ Name = "Not in Database Adams", Country = "AG", DateOfBirth = DateTime.Parse("1982-12-12"), CustomerId = 50
+ }
+ };
+ private readonly Order validOrder = new Order
+ {
+ Amount = 500,
+ CustomerId = 1,
+ VAT = 50
+ };
+ private readonly Order invalidOrder = new Order
+ {
+ Amount = -89,
+ VAT = 50
+ };
+
+ [TestCase]
+ public void GIVEN_VALIDORDER_RETURNS_TRUE()
+ {
+ //Arrange
+ Customer NonUKCustomer = customers[0];
+ validOrder.CustomerId = NonUKCustomer.CustomerId;
+ _orderService.Setup(x => x.Save(validOrder)).Returns(true);
+ _customerService.Setup(x => x.Get(validOrder.CustomerId)).Returns(NonUKCustomer);
+
+ //Act
+ orderService = new OrderService(_orderService.Object,_customerService.Object);
+ bool orderResult = orderService.PlaceOrder(validOrder, validOrder.CustomerId);
+
+ //Asset
+ Assert.AreEqual(orderResult, true);
+ }
+
+ [TestCase]
+ public void GIVEN_INVALIDORDERAMOUNT_RETURNS_FALSE()
+ {
+ //Arrange
+ Customer NonUKCustomer = customers[0];
+ validOrder.CustomerId = NonUKCustomer.CustomerId;
+ _orderService.Setup(x => x.Save(invalidOrder)).Returns(false);
+
+ //Act
+ orderService = new OrderService(_orderService.Object, _customerService.Object);
+ bool orderResult = orderService.PlaceOrder(validOrder, validOrder.CustomerId);
+
+ //Asset
+ Assert.AreEqual(orderResult, false);
+ }
+
+ [TestCase]
+ public void GIVEN_UKCUSTOMER_APPLIES_CORRECT_VAT_AMOUNT_RETURNS_TRUE()
+ {
+ //Arrange
+ Customer UKcustomer = customers[2];
+ validOrder.CustomerId = UKcustomer.CustomerId;
+ _orderService.Setup(x => x.Save(validOrder)).Returns(true);
+ _customerService.Setup(x => x.Get(validOrder.CustomerId)).Returns(UKcustomer);
+
+ //Act
+ orderService = new OrderService(_orderService.Object, _customerService.Object);
+ bool orderResult = orderService.PlaceOrder(validOrder, validOrder.CustomerId);
+
+ //Asset
+ Assert.AreEqual(orderResult, true);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany.Tests/TestsBase.cs b/TechTest/AnyCompany.Tests/TestsBase.cs
new file mode 100644
index 0000000..bf59b13
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/TestsBase.cs
@@ -0,0 +1,115 @@
+//using Microsoft.EntityFrameworkCore;
+
+using AnyCompany;
+using InvestecUnitTestsTests.MockData;
+using AnyCompany.DAL;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore;
+
+namespace InvestecUnitTests
+{
+ public class TestsBase
+ {
+ public RepoAnyCompanyContext RepoContext = RepositoryDataContext();
+ public List Customers = new List
+ {
+ new Customer
+ {
+ Name = "Mike America", Country = "US", DateOfBirth = DateTime.Parse("1987-06-01"), CustomerId = 1
+ },
+ new Customer
+ {
+ Name = "Jonathan Canada", Country = "CN", DateOfBirth = DateTime.Parse("1925-06-01"), CustomerId = 2
+ },
+ new Customer
+ {
+ Name = "FROM THE UK CHINKU", Country = "UK", DateOfBirth = DateTime.Parse("2001-06-01"), CustomerId = 3
+ }
+ ,
+ new Customer
+ {
+ Name = "Not in Database Adams", Country = "AG", DateOfBirth = DateTime.Parse("1982-12-12"), CustomerId = 50
+ }
+ ,
+ new Customer
+ {
+ Name = "Malawi James", Country = "MW", DateOfBirth = DateTime.Parse("1989-02-06"), CustomerId = 4
+ }
+ };
+ public List CustomersWithOrders = new List
+ {
+ new Customer
+ {
+ Name = "I Have 1 Order", Country = "NM", DateOfBirth = DateTime.Parse("1987-06-01"), CustomerId = 12
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 500,
+ OrderId = 12,
+ CustomerId = 12,
+ VAT = 15
+ }
+ }
+ },
+ new Customer
+ {
+ Name = "I Have 2 Orders", Country = "ZW", DateOfBirth = DateTime.Parse("1925-06-01"), CustomerId = 13
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 500,
+ OrderId = 12,
+ CustomerId = 13,
+ VAT = 15
+ }
+
+ ,
+ new Order
+ {
+ Amount = -650,
+ OrderId = 13,
+ CustomerId = 13,
+ VAT = 5
+ }
+ }
+
+ }
+ };
+ public Order ValidOrder = new Order
+ {
+ Amount = 8700,
+ CustomerId = 1,
+ VAT = 2,
+ };
+
+ public Order InValidOrder = new Order
+ {
+ Amount = -10,
+ CustomerId = 2502,
+ VAT = 3,
+ };
+ private static RepoAnyCompanyContext RepositoryDataContext()
+ {
+ return new RepoAnyCompanyContext(new DbContextOptionsBuilder()
+ .UseSqlite("DataSource:inMemory:")
+ .Options);
+ }
+
+ [SetUp]
+ public void Setup()
+ {
+
+ }
+
+ [TearDown]
+ protected void DisposeDatabase()
+ {
+ // RepoContext.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/TechTest/AnyCompany.Tests/app.config b/TechTest/AnyCompany.Tests/app.config
new file mode 100644
index 0000000..47cd2b7
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/app.config
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TechTest/AnyCompany.Tests/packages.config b/TechTest/AnyCompany.Tests/packages.config
new file mode 100644
index 0000000..7afc9a2
--- /dev/null
+++ b/TechTest/AnyCompany.Tests/packages.config
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TechTest/AnyCompany/AnyCompany.csproj b/TechTest/AnyCompany/AnyCompany.csproj
index 5b0498d..f835e03 100644
--- a/TechTest/AnyCompany/AnyCompany.csproj
+++ b/TechTest/AnyCompany/AnyCompany.csproj
@@ -1,18 +1,23 @@
+
Debug
AnyCPU
- {C7E15594-7D8F-4C18-9DD7-14F3FBB1572D}
- Library
- Properties
+ {E882A9A5-1265-4E61-9BBC-9A50989BA147}
+ Exe
AnyCompany
AnyCompany
- v4.6.1
+ v4.7.2
512
+ true
+ true
+
+
+ AnyCPU
true
full
false
@@ -22,6 +27,7 @@
4
+ AnyCPU
pdbonly
true
bin\Release\
@@ -30,8 +36,124 @@
4
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll
+
+
+ ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.1\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+ ..\packages\Microsoft.Bcl.HashCode.1.1.0\lib\net461\Microsoft.Bcl.HashCode.dll
+
+
+ ..\packages\Microsoft.Data.SqlClient.1.0.19269.1\lib\net46\Microsoft.Data.SqlClient.dll
+
+
+ ..\packages\Microsoft.Data.Sqlite.Core.3.1.6\lib\netstandard2.0\Microsoft.Data.Sqlite.dll
+
+
+ ..\packages\Microsoft.DotNet.PlatformAbstractions.3.1.6\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll
+
+
+ ..\packages\Microsoft.EntityFrameworkCore.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Caching.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Caching.Memory.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll
+
+
+ ..\packages\Microsoft.Extensions.Configuration.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll
+
+
+ ..\packages\Microsoft.Extensions.Configuration.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Configuration.Binder.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.3.1.6\lib\net461\Microsoft.Extensions.DependencyInjection.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.DependencyModel.3.1.6\lib\net451\Microsoft.Extensions.DependencyModel.dll
+
+
+ ..\packages\Microsoft.Extensions.Logging.Abstractions.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll
+
+
+ ..\packages\Microsoft.Extensions.Options.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Options.dll
+
+
+ ..\packages\Microsoft.Extensions.Primitives.3.1.6\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll
+
+
+ ..\packages\Microsoft.Identity.Client.3.0.8\lib\net45\Microsoft.Identity.Client.dll
+
+
+ ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\Remotion.Linq.2.0.1\lib\net45\Remotion.Linq.dll
+
+
+ ..\packages\SQLitePCLRaw.core.2.0.2\lib\netstandard2.0\SQLitePCLRaw.core.dll
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll
+
+
+ ..\packages\System.ComponentModel.Annotations.4.7.0\lib\net461\System.ComponentModel.Annotations.dll
+
+
+
+
+ ..\packages\System.Data.Common.4.3.0\lib\net451\System.Data.Common.dll
+ True
+ True
+
+
+ ..\packages\System.Diagnostics.DiagnosticSource.4.7.1\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+
+
+ ..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
+ True
+ True
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+
@@ -40,12 +162,47 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 202008071042307_firstcommit.cs
+
+
+
+
+
+
+
+
+ 202008071042307_firstcommit.cs
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TechTest/AnyCompany/App.config b/TechTest/AnyCompany/App.config
new file mode 100644
index 0000000..95b941b
--- /dev/null
+++ b/TechTest/AnyCompany/App.config
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TechTest/AnyCompany/BUL/Helpers/BusinessRulesHelper.cs b/TechTest/AnyCompany/BUL/Helpers/BusinessRulesHelper.cs
new file mode 100644
index 0000000..4eea22c
--- /dev/null
+++ b/TechTest/AnyCompany/BUL/Helpers/BusinessRulesHelper.cs
@@ -0,0 +1,17 @@
+namespace AnyCompany.BUL.Helpers
+{
+ public static class BusinessRulesHelper
+ {
+ public static decimal DetermineVat(string Country)
+ {
+ //Country should be made into its on Model ideally as it could contain information about itself; Postal Code, City, Town etc
+ //"UK" should not be hardcoded or a string. There should be a dynamic but
+ //consistent source from which to pull these values from. Like a paid for "Countries" webservice or something.
+ return (decimal)(!string.IsNullOrEmpty(Country) && Country.ToUpper() == "UK" ? 0.2 : 0);
+ }
+ public static bool IsValidOrderAmount(decimal orderAmount)
+ {
+ return orderAmount > 0 ? true : false;
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/BUL/Services/CustomerService.cs b/TechTest/AnyCompany/BUL/Services/CustomerService.cs
new file mode 100644
index 0000000..6fa7a75
--- /dev/null
+++ b/TechTest/AnyCompany/BUL/Services/CustomerService.cs
@@ -0,0 +1,26 @@
+using AnyCompany.DAL;
+using System.Collections.Generic;
+
+namespace AnyCompany.BUL.Services
+{
+ //Creating DataSource not responsibilty of Customer Service
+ public class CustomerService
+ {
+ private readonly ICustomerRepository _customerRepository;
+ public CustomerService(ICustomerRepository customerRepository)
+ {
+ _customerRepository = customerRepository;
+ }
+
+ public Customer RetrieveACustomer(int CustomerId)
+ {
+ return _customerRepository.Get(CustomerId);
+ }
+
+ //Return Customers with linked Orders by default
+ public IEnumerable RetrieveCustomers(bool includeOrders = true)
+ {
+ return _customerRepository.GetAll(includeOrders);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/BUL/Services/OrderService.cs b/TechTest/AnyCompany/BUL/Services/OrderService.cs
new file mode 100644
index 0000000..4eb0f69
--- /dev/null
+++ b/TechTest/AnyCompany/BUL/Services/OrderService.cs
@@ -0,0 +1,43 @@
+using AnyCompany.BUL.Helpers;
+using AnyCompany.DAL;
+using System;
+
+namespace AnyCompany.BUL.Services
+{
+ //Creating DataSource not responsibilty of Order Service
+ public class OrderService
+ {
+ private readonly ICustomerRepository _customerRepository;
+ private readonly IOrderRepository _orderRepository;
+ public OrderService(IOrderRepository orderRepository, ICustomerRepository customerRepository)
+ {
+ _orderRepository = orderRepository;
+ _customerRepository = customerRepository;
+ }
+
+ //Business Rules moved to central location
+ public bool PlaceOrder(Order order, int customerId)
+ {
+ if (!BusinessRulesHelper.IsValidOrderAmount(order.Amount))
+ {
+ //Some DI logger here
+ Console.WriteLine("Order Amount should be greater than 0.");
+ return false;
+ }
+
+ Customer customer = _customerRepository.Get(customerId);
+ if (_customerRepository.Get(customerId) == null)
+ {
+ //Some DI logger here
+ Console.WriteLine("No Customer found.");
+ return false;
+ }
+ else
+ {
+ order.VAT = BusinessRulesHelper.DetermineVat(customer.Country);
+ }
+
+ return _orderRepository.Save(order);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/CustomerRepository.cs b/TechTest/AnyCompany/CustomerRepository.cs
deleted file mode 100644
index e3de9b7..0000000
--- a/TechTest/AnyCompany/CustomerRepository.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Data.SqlClient;
-
-namespace AnyCompany
-{
- public static class CustomerRepository
- {
- private static string ConnectionString = @"Data Source=(local);Database=Customers;User Id=admin;Password=password;";
-
- public static Customer Load(int customerId)
- {
- Customer customer = new Customer();
-
- SqlConnection connection = new SqlConnection(ConnectionString);
- connection.Open();
-
- SqlCommand command = new SqlCommand("SELECT * FROM Customer WHERE CustomerId = " + customerId,
- connection);
- var reader = command.ExecuteReader();
-
- while (reader.Read())
- {
- customer.Name = reader["Name"].ToString();
- customer.DateOfBirth = DateTime.Parse(reader["DateOfBirth"].ToString());
- customer.Country = reader["Country"].ToString();
- }
-
- connection.Close();
-
- return customer;
- }
- }
-}
diff --git a/TechTest/AnyCompany/DAL/Data/AnyCompanyContext.cs b/TechTest/AnyCompany/DAL/Data/AnyCompanyContext.cs
new file mode 100644
index 0000000..ec53e85
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Data/AnyCompanyContext.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Configuration;
+using System.Data.Entity;
+namespace AnyCompany.DAL
+{
+ public class AnyCompanyContext : DbContext
+ {
+ public AnyCompanyContext() : base(@ConfigurationManager.ConnectionStrings["AnyCompanyConnection"]?.ConnectionString)
+ {
+ }
+ public DbSet Orders { get; set; }
+ public DbSet Customers { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.cs b/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.cs
new file mode 100644
index 0000000..1d34be0
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.cs
@@ -0,0 +1,44 @@
+namespace AnyCompany.Migrations
+{
+ using System;
+ using System.Data.Entity.Migrations;
+
+ public partial class firstcommit : DbMigration
+ {
+ public override void Up()
+ {
+ CreateTable(
+ "dbo.Customers",
+ c => new
+ {
+ CustomerId = c.Int(nullable: false, identity: true),
+ Country = c.String(),
+ DateOfBirth = c.DateTime(nullable: false),
+ Name = c.String(),
+ })
+ .PrimaryKey(t => t.CustomerId);
+
+ CreateTable(
+ "dbo.Orders",
+ c => new
+ {
+ OrderId = c.Int(nullable: false, identity: true),
+ CustomerId = c.Int(nullable: false),
+ Amount = c.Decimal(nullable: false, precision: 18, scale: 2),
+ VAT = c.Decimal(nullable: false, precision: 18, scale: 2),
+ })
+ .PrimaryKey(t => t.OrderId)
+ .ForeignKey("dbo.Customers", t => t.CustomerId, cascadeDelete: true)
+ .Index(t => t.CustomerId);
+
+ }
+
+ public override void Down()
+ {
+ DropForeignKey("dbo.Orders", "CustomerId", "dbo.Customers");
+ DropIndex("dbo.Orders", new[] { "CustomerId" });
+ DropTable("dbo.Orders");
+ DropTable("dbo.Customers");
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.designer.cs b/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.designer.cs
new file mode 100644
index 0000000..251ef25
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.designer.cs
@@ -0,0 +1,29 @@
+//
+namespace AnyCompany.Migrations
+{
+ using System.CodeDom.Compiler;
+ using System.Data.Entity.Migrations;
+ using System.Data.Entity.Migrations.Infrastructure;
+ using System.Resources;
+
+ [GeneratedCode("EntityFramework.Migrations", "6.4.4")]
+ public sealed partial class firstcommit : IMigrationMetadata
+ {
+ private readonly ResourceManager Resources = new ResourceManager(typeof(firstcommit));
+
+ string IMigrationMetadata.Id
+ {
+ get { return "202008071042307_firstcommit"; }
+ }
+
+ string IMigrationMetadata.Source
+ {
+ get { return null; }
+ }
+
+ string IMigrationMetadata.Target
+ {
+ get { return Resources.GetString("Target"); }
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.resx b/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.resx
new file mode 100644
index 0000000..d0fe62e
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Data/Migrations/202008071042307_firstcommit.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ H4sIAAAAAAAEAM1Z227jNhB9L9B/IPTUFtkoyb5sDXsXXicpjCZxECVB3wJGGjtEKVIlqcDGol/Wh35Sf6FD3SxRli+5LgIENjlzOByeGc7Q//3zb//LPObkEZRmUgy8w/0Dj4AIZcTEbOClZvrhk/fl848/9E+ieE5uS7mPVg41hR54D8YkPd/X4QPEVO/HLFRSy6nZD2Xs00j6RwcHv/qHhz4ghIdYhPSvUmFYDNkX/DqSIoTEpJSfywi4LsZxJshQyQWNQSc0hIE3FIuRjBMqFvvHwzOPDDmjaEUAfOoRKoQ01KCNvRsNgVFSzIIEByi/XiSAclPKNRS295bi227j4Mhuw18qllBhqo2MdwQ8/Fj4xXfVn+Rdr/Ibeu4EPWwWdteZ9wbeKFsClEfcxXojrqxgw7ml+B5ZDu5VDECi2L89Mkq5SRUMBKRGUb5HLtN7zsLfYXEt/wQxECnndbvQMpxrDODQpZIJKLO4gqlj7TjyiN/U912ASn2Fbr6vsTAfjzxygcbQew4VDWo+CIxU8BsIUNRAdEmNAYWnOI4gc2TLCndNiZRWi3JBpB5GkEfO6fwMxMw8DDz86JFTNoeoHCmMuBEMAw6VjEph0zrHaN1k+pUp81CuZYeuMZpW7G89lv3/8gZf0Ec2y3zqLDdREbLHI1fAs2n9wJI8cCuy3ZUyp0rGV5LXDrOYugtkqkJrtlw9f03VDEzTqr6/jIa1MZJhbBkgmew7RUe29lNCo1J8s7jYOhbX4wxjG2AV5SFkMeUeuVT4qbi7PnkkCKlF3B3+dnj9QthdXBtqLUOW+dRxTUn6poEnIiIbIiAP3Hr8YPwi41iCHEMT0G7P5dJEHAMHA2QY5tfUiOqQRm0H4TaibS0qY65mURFJTXN+aa2ClAZlmUQ5FgEag4QJ0+Y/EyFLKF/vEEdtx2vFbrlayJ05hgSEZfx6Bzzfgmoh5zA2+anv1/jVTnGoY1ADVBlNVdKyMzA3K3IeFlBF2tNFpnfpYJEDMM7GMHsvI6DFT389SJn/WwgFnxz12qbbhlSXSU2q475xz2Fz8FWGNzbeOtDNMVMDKu11I7G5yxW5pjreZeHs55VzWWH7HSV2/5wmCV78tZK7GCFBXm+PPgS7F6NxjuGHekVNWllbrYRXDJ2BM2trqghOmdIGKxx6T22mHUVxS6xN5g6Oleu5fG0fWkm+UsN+diPHth9LYrdDv9A9xa3FNnNkF+kK2rRVs76HcqrW3KUjydNYbE4pa9DKirUBVQ5uj9OoSOtYjYnt8fKqtA6Uj7QR+r7j41Y6bZ1k645rUmMr4nTmjK1Zkyez3SnTodflyarYqzuzo3Rcy5QX5V1ZydWRyrHtUbKCrQ6RDbwxR1r51xWpVq/ysJNv+0Xu2/zu0UqGuYgtU+Uji2wiDBbaQLxvBfaDv/iIM7BOLQXOqWBT0CZvPbyjg8Mj5/nk+3nK8LWO+JbvGe/+usCslzf2STt2JM6DgnikKnyg6qeYzn+ugz3x0SDCIfPcR4MdjNqxBX/Hnvh1TnM1aVpF9xiL//nA+5ap9cj4j7ul5h7JLO2RA/L3M/vn6BX752div17//J4dc9G+vHGD/JYtcVdN8512wO3eYrvudm1zm1/JGAL3Es86p3hnd7i69+1ufVeBd3SMb9cWr2yE1/bBjV3WqtpX6Xrb1RUSqfbbE7JYs9kSwv4SJSBsUKiSGYupLNnsWFSKOFnxHAzFi5YOlWFTGhqcDkHr7KH9lvIURU7ie4jGYpKaJDW4ZYjveaP9shGxbv2stW/a3J8k2fv6S2wBzWS2VpiIrynjUWX36YrM3QFhQ624Su1ZGnulzhYV0oUUWwIV7qsyxDXECUcwPREBfYSn2Haj4QxmNFyURXI3yOaDaLq9f8zoTNFYFxhLffyKHI7i+ef/AeNazcOCHQAA
+
+
+ dbo
+
+
\ No newline at end of file
diff --git a/TechTest/AnyCompany/DAL/Data/Migrations/Configuration.cs b/TechTest/AnyCompany/DAL/Data/Migrations/Configuration.cs
new file mode 100644
index 0000000..2b746c2
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Data/Migrations/Configuration.cs
@@ -0,0 +1,70 @@
+namespace AnyCompany.Migrations
+{
+ using AnyCompany.DAL;
+ using System;
+ using System.Collections.Generic;
+ using System.Data.Entity;
+ using System.Data.Entity.Migrations;
+ using System.Linq;
+
+ internal sealed class Configuration : DbMigrationsConfiguration
+ {
+ public Configuration()
+ {
+ AutomaticMigrationsEnabled = false;
+ }
+
+ protected override void Seed(AnyCompanyContext context)
+ {
+ List dummyCustomersWithOrders = new List
+ {
+ new Customer
+ {
+ Name = "I Have 1 Order", Country = "NM", DateOfBirth = DateTime.Parse("1987-06-01")
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 500,
+ VAT = 1
+ }
+ }
+ },
+ new Customer
+ {
+ Name = "I have zero Orders", Country = "ZA", DateOfBirth = DateTime.Parse("1985-09-11")
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 450,
+ VAT = 12
+ }
+ }
+ },
+ new Customer
+ {
+ Name = "I Have 2 Orders", Country = "ZW", DateOfBirth = DateTime.Parse("1925-06-01")
+ , Orders = new List()
+ {
+ new Order
+ {
+ Amount = 6799,
+ VAT = 4
+ }
+
+ ,
+ new Order
+ {
+ Amount = 650,
+ VAT = 5
+ }
+ }
+ }
+ };
+
+ context.Customers.AddRange(dummyCustomersWithOrders);
+ context.SaveChanges();
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Interfaces/ICustomerRepository.cs b/TechTest/AnyCompany/DAL/Interfaces/ICustomerRepository.cs
new file mode 100644
index 0000000..2e9e69b
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Interfaces/ICustomerRepository.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace AnyCompany.DAL
+{
+ public interface ICustomerRepository
+ {
+ Customer Get(int CustomerId);
+ IEnumerable GetAll(bool includeOrders = true);
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Interfaces/IOrderRepository.cs b/TechTest/AnyCompany/DAL/Interfaces/IOrderRepository.cs
new file mode 100644
index 0000000..bec6f42
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Interfaces/IOrderRepository.cs
@@ -0,0 +1,8 @@
+
+namespace AnyCompany.DAL
+{
+ public interface IOrderRepository
+ {
+ bool Save(Order order);
+ }
+}
diff --git a/TechTest/AnyCompany/Customer.cs b/TechTest/AnyCompany/DAL/Models/Customer.cs
similarity index 51%
rename from TechTest/AnyCompany/Customer.cs
rename to TechTest/AnyCompany/DAL/Models/Customer.cs
index aa994b6..c7bda3d 100644
--- a/TechTest/AnyCompany/Customer.cs
+++ b/TechTest/AnyCompany/DAL/Models/Customer.cs
@@ -1,13 +1,16 @@
using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
namespace AnyCompany
{
public class Customer
{
+ [Key]
+ public int CustomerId { get; set; }
public string Country { get; set; }
-
public DateTime DateOfBirth { get; set; }
-
public string Name { get; set; }
+ public List Orders { get; set; } = new List();
}
}
diff --git a/TechTest/AnyCompany/DAL/Models/Order.cs b/TechTest/AnyCompany/DAL/Models/Order.cs
new file mode 100644
index 0000000..0af961d
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Models/Order.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace AnyCompany
+{
+ public class Order
+ {
+ [Key]
+ public int OrderId { get; set; }
+
+ //[ForeignKey("Order")]
+ public int CustomerId { get; set; }
+ public decimal Amount { get; set; }
+ public decimal VAT { get; set; }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Repositories/CustomerRepository.cs b/TechTest/AnyCompany/DAL/Repositories/CustomerRepository.cs
new file mode 100644
index 0000000..d57871d
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Repositories/CustomerRepository.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.Data.SqlClient;
+using System.Linq;
+
+namespace AnyCompany.DAL.Repositories
+{
+ internal static class CustomerRepository
+ {
+ public static Customer Get(int CustomerId)
+ {
+ try
+ {
+ using (AnyCompanyContext anyCompanyContext = new AnyCompanyContext())
+ {
+ return anyCompanyContext.Customers.SingleOrDefault(c => c.CustomerId == CustomerId);
+ }
+ }
+ catch (SqlException ex)
+ {
+ //Logger here
+ Console.WriteLine(ex.Message);
+ }
+ catch (Exception ex)
+ {
+ //Logger here
+ Console.WriteLine(ex.Message);
+ }
+ return null;
+ }
+ public static IEnumerable GetAll(bool includeOrders = true)
+ {
+ try
+ {
+ using (AnyCompanyContext anyCompanyContext = new AnyCompanyContext())
+ {
+ return includeOrders ? anyCompanyContext.Customers.Include(c => c.Orders).ToList() : anyCompanyContext.Customers.ToList();
+ }
+ }
+ catch (SqlException ex)
+ {
+ //Injected Logger
+ Console.WriteLine(ex.Message);
+ }
+ catch (Exception ex)
+ {
+ //Injected Logger
+ Console.WriteLine(ex.Message);
+ }
+ return null;
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Repositories/CustomerRepositoryWrapper.cs b/TechTest/AnyCompany/DAL/Repositories/CustomerRepositoryWrapper.cs
new file mode 100644
index 0000000..d3e2fee
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Repositories/CustomerRepositoryWrapper.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+
+namespace AnyCompany.DAL.Repositories
+{
+ public class CustomerRepositoryWrapper : ICustomerRepository
+ {
+ public Customer Get(int CustomerId)
+ {
+ //Use a mapper like AutoMapper here to change Model to user friendly DTO if necessary
+ return CustomerRepository.Get(CustomerId);
+ }
+
+ public IEnumerable GetAll(bool includeOrders = true)
+ {
+ //Use a mapper like AutoMapper here to change Model to user friendly DTO if necessary
+ return CustomerRepository.GetAll(includeOrders);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Repositories/OrderRepository.cs b/TechTest/AnyCompany/DAL/Repositories/OrderRepository.cs
new file mode 100644
index 0000000..2f66f8f
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Repositories/OrderRepository.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Data.SqlClient;
+
+namespace AnyCompany.DAL.Repositories
+{
+ internal class OrderRepository
+ {
+ internal bool Save(Order order)
+ {
+ try
+ {
+ using (AnyCompanyContext context = new AnyCompanyContext())
+ {
+ context.Orders.Add(order);
+ return context.SaveChanges() > 0;
+ }
+ }
+ catch (SqlException ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ return false;
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/DAL/Repositories/OrderRepositoryWrapper.cs b/TechTest/AnyCompany/DAL/Repositories/OrderRepositoryWrapper.cs
new file mode 100644
index 0000000..7e38182
--- /dev/null
+++ b/TechTest/AnyCompany/DAL/Repositories/OrderRepositoryWrapper.cs
@@ -0,0 +1,11 @@
+namespace AnyCompany.DAL.Repositories
+{
+ public class OrderRepositoryWrapper : IOrderRepository
+ {
+ public bool Save(Order order)
+ {
+ //Use a mapper like AutoMapper here to change Model to user friendly DTO if necessary
+ return new OrderRepository().Save(order);
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/Order.cs b/TechTest/AnyCompany/Order.cs
deleted file mode 100644
index fec8e7b..0000000
--- a/TechTest/AnyCompany/Order.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace AnyCompany
-{
- public class Order
- {
- public int OrderId { get; set; }
- public double Amount { get; set; }
- public double VAT { get; set; }
- }
-}
diff --git a/TechTest/AnyCompany/OrderRepository.cs b/TechTest/AnyCompany/OrderRepository.cs
deleted file mode 100644
index 3229885..0000000
--- a/TechTest/AnyCompany/OrderRepository.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.Data.SqlClient;
-
-namespace AnyCompany
-{
- internal class OrderRepository
- {
- private static string ConnectionString = @"Data Source=(local);Database=Orders;User Id=admin;Password=password;";
-
- public void Save(Order order)
- {
- SqlConnection connection = new SqlConnection(ConnectionString);
- connection.Open();
-
- SqlCommand command = new SqlCommand("INSERT INTO Orders VALUES (@OrderId, @Amount, @VAT)", connection);
-
- command.Parameters.AddWithValue("@OrderId", order.OrderId);
- command.Parameters.AddWithValue("@Amount", order.Amount);
- command.Parameters.AddWithValue("@VAT", order.VAT);
-
- command.ExecuteNonQuery();
-
- connection.Close();
- }
- }
-}
diff --git a/TechTest/AnyCompany/OrderService.cs b/TechTest/AnyCompany/OrderService.cs
deleted file mode 100644
index ebfb103..0000000
--- a/TechTest/AnyCompany/OrderService.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace AnyCompany
-{
- public class OrderService
- {
- private readonly OrderRepository orderRepository = new OrderRepository();
-
- public bool PlaceOrder(Order order, int customerId)
- {
- Customer customer = CustomerRepository.Load(customerId);
-
- if (order.Amount == 0)
- return false;
-
- if (customer.Country == "UK")
- order.VAT = 0.2d;
- else
- order.VAT = 0;
-
- orderRepository.Save(order);
-
- return true;
- }
- }
-}
diff --git a/TechTest/AnyCompany/Program.cs b/TechTest/AnyCompany/Program.cs
new file mode 100644
index 0000000..90389b2
--- /dev/null
+++ b/TechTest/AnyCompany/Program.cs
@@ -0,0 +1,38 @@
+using AnyCompany.BUL.Helpers;
+using AnyCompany.BUL.Services;
+using AnyCompany.DAL;
+using AnyCompany.DAL.Repositories;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AnyCompany
+{
+ class Program
+ { static void Main(string[] args)
+ {
+ CustomerService c = new CustomerService(new CustomerRepositoryWrapper());
+ Customer customer = c.RetrieveACustomer(1);
+ if (customer != null)
+ {
+ Console.WriteLine("Customer is " + customer.Name);
+ Console.WriteLine();
+
+ IEnumerable customers = c.RetrieveCustomers(true);
+ Console.WriteLine("Customers are:");
+ customers.ToList().ForEach(i => Console.Write("Name: {0}\t Order counts: {1}\n", i.Name, i.Orders.Count));
+
+ Console.WriteLine("\n\n=============================");
+ OrderService s = new OrderService(new OrderRepositoryWrapper(), new CustomerRepositoryWrapper());
+ Order order = new Order { Amount = 2456, CustomerId = customer.CustomerId, VAT = BusinessRulesHelper.DetermineVat(customer.Country) };
+ bool result = s.PlaceOrder(order, customer.CustomerId);
+ Console.WriteLine("Added Order succesfully = " + result);
+ }
+ else
+ {
+ Console.WriteLine("Could be no data in the DB... Mmm..");
+ }
+ Console.ReadKey();
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/Properties/AssemblyInfo.cs b/TechTest/AnyCompany/Properties/AssemblyInfo.cs
index bcdfb17..794f339 100644
--- a/TechTest/AnyCompany/Properties/AssemblyInfo.cs
+++ b/TechTest/AnyCompany/Properties/AssemblyInfo.cs
@@ -8,9 +8,9 @@
[assembly: AssemblyTitle("AnyCompany")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Investec Bank")]
+[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AnyCompany")]
-[assembly: AssemblyCopyright("Copyright © Investec Bank 2018")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -20,7 +20,7 @@
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("c7e15594-7d8f-4c18-9dd7-14f3fbb1572d")]
+[assembly: Guid("e882a9a5-1265-4e61-9bbc-9a50989ba147")]
// Version information for an assembly consists of the following four values:
//
diff --git a/TechTest/AnyCompany/Properties/Settings.Designer.cs b/TechTest/AnyCompany/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..65b88b7
--- /dev/null
+++ b/TechTest/AnyCompany/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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.
+//
+//------------------------------------------------------------------------------
+
+namespace AnyCompany.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.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;
+ }
+ }
+ }
+}
diff --git a/TechTest/AnyCompany/Properties/Settings.settings b/TechTest/AnyCompany/Properties/Settings.settings
new file mode 100644
index 0000000..049245f
--- /dev/null
+++ b/TechTest/AnyCompany/Properties/Settings.settings
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/TechTest/AnyCompany/packages.config b/TechTest/AnyCompany/packages.config
new file mode 100644
index 0000000..b3b266b
--- /dev/null
+++ b/TechTest/AnyCompany/packages.config
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TechTest/TechTest.sln b/TechTest/TechTest.sln
index 1c1c57a..7058c9a 100644
--- a/TechTest/TechTest.sln
+++ b/TechTest/TechTest.sln
@@ -1,11 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2005
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30330.147
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnyCompany", "AnyCompany\AnyCompany.csproj", "{C7E15594-7D8F-4C18-9DD7-14F3FBB1572D}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnyCompany", "AnyCompany\AnyCompany.csproj", "{E882A9A5-1265-4E61-9BBC-9A50989BA147}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnyCompany.Tests", "AnyCompany.Tests\AnyCompany.Tests.csproj", "{CD5D577E-BDC9-4DFC-AC6A-B1DA474995F3}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnyCompany.Tests", "AnyCompany.Tests\AnyCompany.Tests.csproj", "{60CFE149-CB3F-4227-8EAD-4E16C0796535}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B6D3C1BB-2A37-4E17-9EE3-DEF28286E782}"
ProjectSection(SolutionItems) = preProject
@@ -18,14 +18,14 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C7E15594-7D8F-4C18-9DD7-14F3FBB1572D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C7E15594-7D8F-4C18-9DD7-14F3FBB1572D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C7E15594-7D8F-4C18-9DD7-14F3FBB1572D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C7E15594-7D8F-4C18-9DD7-14F3FBB1572D}.Release|Any CPU.Build.0 = Release|Any CPU
- {CD5D577E-BDC9-4DFC-AC6A-B1DA474995F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CD5D577E-BDC9-4DFC-AC6A-B1DA474995F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CD5D577E-BDC9-4DFC-AC6A-B1DA474995F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CD5D577E-BDC9-4DFC-AC6A-B1DA474995F3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E882A9A5-1265-4E61-9BBC-9A50989BA147}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E882A9A5-1265-4E61-9BBC-9A50989BA147}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E882A9A5-1265-4E61-9BBC-9A50989BA147}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E882A9A5-1265-4E61-9BBC-9A50989BA147}.Release|Any CPU.Build.0 = Release|Any CPU
+ {60CFE149-CB3F-4227-8EAD-4E16C0796535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {60CFE149-CB3F-4227-8EAD-4E16C0796535}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {60CFE149-CB3F-4227-8EAD-4E16C0796535}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {60CFE149-CB3F-4227-8EAD-4E16C0796535}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/TechTest/package-lock.json b/TechTest/package-lock.json
new file mode 100644
index 0000000..48e341a
--- /dev/null
+++ b/TechTest/package-lock.json
@@ -0,0 +1,3 @@
+{
+ "lockfileVersion": 1
+}