Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\ClearBank.DeveloperTest\ClearBank.DeveloperTest.csproj" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.8.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0" />
</ItemGroup>

</Project>
73 changes: 73 additions & 0 deletions ClearBank.DeveloperTest.Tests/Tests/PaymentServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using ClearBank.DeveloperTest.Data;
using ClearBank.DeveloperTest.Services;
using ClearBank.DeveloperTest.Types;
using System;
using Xunit;

namespace ClearBank.DeveloperTest.Tests
{
public class PaymentServiceTests
{
private class FakeStore : IAccountDataStore
{
public Account Account { get; set; }

public Account GetAccount(string accountNumber) => Account;

public void UpdateAccount(Account account) => Account = account;
}

private class FakeFactory : IAccountDataStoreFactory
{
public FakeStore Store { get; } = new FakeStore();

public IAccountDataStore Create(string type) => Store;
}

[Fact]
public void Bacs_Fails_When_Account_Null()
{
var factory = new FakeFactory();
factory.Store.Account = null;

var svc = new PaymentService(factory);

var req = new MakePaymentRequest { DebtorAccountNumber = "123", Amount = 10m, PaymentScheme = PaymentScheme.Bacs };

var result = svc.MakePayment(req);

Assert.False(result.Success);
}

[Fact]
public void FasterPayments_Fails_When_Insufficient_Balance()
{
var factory = new FakeFactory();
factory.Store.Account = new Account { AccountNumber = "123", Balance = 5m, AllowedPaymentSchemes = AllowedPaymentSchemes.FasterPayments };

var svc = new PaymentService(factory);

var req = new MakePaymentRequest { DebtorAccountNumber = "123", Amount = 10m, PaymentScheme = PaymentScheme.FasterPayments };

var result = svc.MakePayment(req);

Assert.False(result.Success);
}

[Fact]
public void Chaps_Succeeds_When_Live_And_Allowed()
{
var factory = new FakeFactory();
factory.Store.Account = new Account { AccountNumber = "123", Balance = 100m, AllowedPaymentSchemes = AllowedPaymentSchemes.Chaps, Status = AccountStatus.Live };

var svc = new PaymentService(factory);

var req = new MakePaymentRequest { DebtorAccountNumber = "123", Amount = 10m, PaymentScheme = PaymentScheme.Chaps };

var result = svc.MakePayment(req);

Assert.True(result.Success);
Assert.Equal(90m, factory.Store.Account.Balance);
}
}
}
2 changes: 1 addition & 1 deletion ClearBank.DeveloperTest/Data/AccountDataStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace ClearBank.DeveloperTest.Data
{
public class AccountDataStore
public class AccountDataStore : IAccountDataStore
{
public Account GetAccount(string accountNumber)
{
Expand Down
17 changes: 17 additions & 0 deletions ClearBank.DeveloperTest/Data/AccountDataStoreFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Configuration;

namespace ClearBank.DeveloperTest.Data
{
public class AccountDataStoreFactory : IAccountDataStoreFactory
{
public IAccountDataStore Create(string type)
{
if (type == "Backup")
{
return new BackupAccountDataStore();
}

return new AccountDataStore();
}
}
}
2 changes: 1 addition & 1 deletion ClearBank.DeveloperTest/Data/BackupAccountDataStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace ClearBank.DeveloperTest.Data
{
public class BackupAccountDataStore
public class BackupAccountDataStore : IAccountDataStore
{
public Account GetAccount(string accountNumber)
{
Expand Down
10 changes: 10 additions & 0 deletions ClearBank.DeveloperTest/Data/IAccountDataStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using ClearBank.DeveloperTest.Types;

namespace ClearBank.DeveloperTest.Data
{
public interface IAccountDataStore
{
Account GetAccount(string accountNumber);
void UpdateAccount(Account account);
}
}
7 changes: 7 additions & 0 deletions ClearBank.DeveloperTest/Data/IAccountDataStoreFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ClearBank.DeveloperTest.Data
{
public interface IAccountDataStoreFactory
{
IAccountDataStore Create(string type);
}
}
67 changes: 18 additions & 49 deletions ClearBank.DeveloperTest/Services/PaymentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,44 @@ namespace ClearBank.DeveloperTest.Services
{
public class PaymentService : IPaymentService
{
private readonly IAccountDataStoreFactory _factory;

// Default constructor preserves original behavior
public PaymentService() : this(new AccountDataStoreFactory()) { }

// Allow injection for testability
public PaymentService(IAccountDataStoreFactory factory)
{
_factory = factory;
}

public MakePaymentResult MakePayment(MakePaymentRequest request)
{
var dataStoreType = ConfigurationManager.AppSettings["DataStoreType"];

Account account = null;
var accountStore = _factory.Create(dataStoreType);
var account = accountStore.GetAccount(request.DebtorAccountNumber);

if (dataStoreType == "Backup")
{
var accountDataStore = new BackupAccountDataStore();
account = accountDataStore.GetAccount(request.DebtorAccountNumber);
}
else
{
var accountDataStore = new AccountDataStore();
account = accountDataStore.GetAccount(request.DebtorAccountNumber);
}

var result = new MakePaymentResult();
var result = new MakePaymentResult { Success = true };

result.Success = true;

switch (request.PaymentScheme)
{
case PaymentScheme.Bacs:
if (account == null)
{
result.Success = false;
}
else if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Bacs))
if (account == null || !account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Bacs))
{
result.Success = false;
}
break;

case PaymentScheme.FasterPayments:
if (account == null)
{
result.Success = false;
}
else if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.FasterPayments))
{
result.Success = false;
}
else if (account.Balance < request.Amount)
if (account == null || !account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.FasterPayments) || account.Balance < request.Amount)
{
result.Success = false;
}
break;

case PaymentScheme.Chaps:
if (account == null)
{
result.Success = false;
}
else if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Chaps))
{
result.Success = false;
}
else if (account.Status != AccountStatus.Live)
if (account == null || !account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Chaps) || account.Status != AccountStatus.Live)
{
result.Success = false;
}
Expand All @@ -74,17 +53,7 @@ public MakePaymentResult MakePayment(MakePaymentRequest request)
if (result.Success)
{
account.Balance -= request.Amount;

if (dataStoreType == "Backup")
{
var accountDataStore = new BackupAccountDataStore();
accountDataStore.UpdateAccount(account);
}
else
{
var accountDataStore = new AccountDataStore();
accountDataStore.UpdateAccount(account);
}
accountStore.UpdateAccount(account);
}

return result;
Expand Down