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
28 changes: 18 additions & 10 deletions RefactorThis.Domain.Tests/InvoicePaymentProcessorTests.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using RefactorThis.Domain.PaymentProcessor;
using RefactorThis.Domain.PaymentProcessor.Validators;
using RefactorThis.Persistence;

namespace RefactorThis.Domain.Tests
{
[TestFixture]
public class InvoicePaymentProcessorTests
{
{
private readonly IPaymentProcessorValidator _paymentProcessorValidator;
public InvoicePaymentProcessorTests()
{
_paymentProcessorValidator = new PaymentProcessorValidator(new PaymentValidatorAbstractFactory());
}

[Test]
public void ProcessPayment_Should_ThrowException_When_NoInoiceFoundForPaymentReference( )
{
var repo = new InvoiceRepository( );

Invoice invoice = null;
var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor( repo, _paymentProcessorValidator);

var payment = new Payment( );
var failureMessage = "";
Expand Down Expand Up @@ -45,7 +53,7 @@ public void ProcessPayment_Should_ReturnFailureMessage_When_NoPaymentNeeded( )

repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( );

Expand Down Expand Up @@ -73,7 +81,7 @@ public void ProcessPayment_Should_ReturnFailureMessage_When_InvoiceAlreadyFullyP
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( );

Expand All @@ -100,7 +108,7 @@ public void ProcessPayment_Should_ReturnFailureMessage_When_PartialPaymentExists
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( )
{
Expand All @@ -124,7 +132,7 @@ public void ProcessPayment_Should_ReturnFailureMessage_When_NoPartialPaymentExis
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( )
{
Expand Down Expand Up @@ -154,7 +162,7 @@ public void ProcessPayment_Should_ReturnFullyPaidMessage_When_PartialPaymentExis
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( )
{
Expand All @@ -178,7 +186,7 @@ public void ProcessPayment_Should_ReturnFullyPaidMessage_When_NoPartialPaymentEx
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( )
{
Expand Down Expand Up @@ -208,7 +216,7 @@ public void ProcessPayment_Should_ReturnPartiallyPaidMessage_When_PartialPayment
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( )
{
Expand All @@ -232,7 +240,7 @@ public void ProcessPayment_Should_ReturnPartiallyPaidMessage_When_NoPartialPayme
};
repo.Add( invoice );

var paymentProcessor = new InvoicePaymentProcessor( repo );
var paymentProcessor = new InvoicePaymentProcessor(repo, _paymentProcessorValidator);

var payment = new Payment( )
{
Expand Down
14 changes: 14 additions & 0 deletions RefactorThis.Domain/Common/ValidationModel/ValidationStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace RefactorThis.Domain.Common.ValidationModel
{
public class ValidationStatus
{
public bool Success { get;}
public string Message { get;}

public ValidationStatus(bool success, string message)
{
Success = success;
Message = message;
}
}
}
94 changes: 0 additions & 94 deletions RefactorThis.Domain/InvoicePaymentProcessor.cs

This file was deleted.

39 changes: 39 additions & 0 deletions RefactorThis.Domain/PaymentProcessor/InvoicePaymentProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using RefactorThis.Domain.PaymentProcessor.Validators;
using RefactorThis.Persistence;

namespace RefactorThis.Domain.PaymentProcessor
{
public class InvoicePaymentProcessor
{
private readonly InvoiceRepository _invoiceRepository;
private readonly IPaymentProcessorValidator _paymentProcessorValidator;

public InvoicePaymentProcessor( InvoiceRepository invoiceRepository, IPaymentProcessorValidator paymentProcessorValidator )
{
_invoiceRepository = invoiceRepository;
_paymentProcessorValidator = paymentProcessorValidator;
}

public string ProcessPayment( Payment payment )
{
var inv = _invoiceRepository.GetInvoice( payment.Reference );

var validationStatus = _paymentProcessorValidator.Validate(inv, payment);

if (validationStatus.Success)
{
AddPayment(payment, inv);
}

inv.Save();

return validationStatus.Message;
}

private static void AddPayment(Payment payment, Invoice inv)
{
inv.AmountPaid += payment.Amount;
inv.Payments.Add(payment);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Linq;
using RefactorThis.Domain.Common.ValidationModel;
using RefactorThis.Persistence;

namespace RefactorThis.Domain.PaymentProcessor.Validators
{
public class AdditionalPaymentValidator : IPaymentValidator
{
public ValidationStatus Validate(Invoice invoice, Payment payment)
{
if (InvoiceIsPaid(invoice))
{
return new ValidationStatus(false, "invoice was already fully paid");
}

if (PaymentGreaterThanAmountRemaining(payment, invoice))
{
return new ValidationStatus(false, "the payment is greater than the partial amount remaining");
}

return IsFinalPayment(payment, invoice) ?
new ValidationStatus(true, "final partial payment received, invoice is now fully paid") :
new ValidationStatus(true, "another partial payment received, still not fully paid");
}

private static bool InvoiceIsPaid(Invoice invoice)
{
return invoice.Payments.Sum(x => x.Amount) != 0 && invoice.Amount == invoice.Payments.Sum(x => x.Amount);
}

private static bool PaymentGreaterThanAmountRemaining(Payment payment, Invoice invoice)
{
return invoice.Payments.Sum(x => x.Amount) != 0 && payment.Amount > (invoice.Amount - invoice.AmountPaid);
}

private static bool IsFinalPayment(Payment payment, Invoice invoice)
{
return (invoice.Amount - invoice.AmountPaid) == payment.Amount;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using RefactorThis.Domain.Common.ValidationModel;
using RefactorThis.Persistence;

namespace RefactorThis.Domain.PaymentProcessor.Validators
{
public class FirstPaymentValidator : IPaymentValidator
{
public ValidationStatus Validate(Invoice invoice, Payment payment)
{
if (PaymentGreaterThanAmount(invoice, payment))
{
return new ValidationStatus(false, "the payment is greater than the invoice amount");
}

return PaymentEqualsAmount(invoice, payment) ?
new ValidationStatus(true, "invoice is now fully paid") :
new ValidationStatus(true, "invoice is now partially paid");
}

private static bool PaymentEqualsAmount(Invoice invoice, Payment payment)
{
return invoice.Amount == payment.Amount;
}

private static bool PaymentGreaterThanAmount(Invoice invoice, Payment payment)
{
return payment.Amount > invoice.Amount;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using RefactorThis.Domain.Common.ValidationModel;
using RefactorThis.Persistence;

namespace RefactorThis.Domain.PaymentProcessor.Validators
{
public interface IPaymentProcessorValidator
{
ValidationStatus Validate(Invoice invoice, Payment payment);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using RefactorThis.Domain.Common.ValidationModel;
using RefactorThis.Persistence;

namespace RefactorThis.Domain.PaymentProcessor.Validators
{
public interface IPaymentValidator
{
ValidationStatus Validate(Invoice invoice, Payment payment);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace RefactorThis.Domain.PaymentProcessor.Validators
{
public interface IPaymentValidatorAbstractFactory
{
IPaymentValidator GetFirstPaymentValidator();
IPaymentValidator GetAdditionalPaymentValidator();
}
}
Loading