From a275b6200965126d81b0f2c509ce53b19242096c Mon Sep 17 00:00:00 2001 From: pm-marco Date: Wed, 28 May 2025 22:08:58 +1200 Subject: [PATCH] Refactor by Marco --- .../InvoicePaymentProcessorTests.cs | 481 +++++++++--------- .../RefactorThis.Domain.Tests.csproj | 131 ++--- RefactorThis.Domain/InvoiceService.cs | 224 ++++---- .../RefactorThis.Domain.csproj | 148 ++++-- .../common/ProcessPaymentExceptionMessage.cs | 8 + .../common/enums/ProcessPaymentStatus.cs | 18 + RefactorThis.Persistence/Invoice.cs | 31 -- RefactorThis.Persistence/InvoiceRepository.cs | 21 - RefactorThis.Persistence/Payment.cs | 8 - RefactorThis.Persistence/enums/InvoiceType.cs | 8 + RefactorThis.Persistence/models/Invoice.cs | 36 ++ RefactorThis.Persistence/models/Payment.cs | 18 + .../repositories/IInvoiceRepository.cs | 11 + .../repositories/InvoiceRepository.cs | 24 + 14 files changed, 619 insertions(+), 548 deletions(-) create mode 100644 RefactorThis.Domain/common/ProcessPaymentExceptionMessage.cs create mode 100644 RefactorThis.Domain/common/enums/ProcessPaymentStatus.cs delete mode 100644 RefactorThis.Persistence/Invoice.cs delete mode 100644 RefactorThis.Persistence/InvoiceRepository.cs delete mode 100644 RefactorThis.Persistence/Payment.cs create mode 100644 RefactorThis.Persistence/enums/InvoiceType.cs create mode 100644 RefactorThis.Persistence/models/Invoice.cs create mode 100644 RefactorThis.Persistence/models/Payment.cs create mode 100644 RefactorThis.Persistence/repositories/IInvoiceRepository.cs create mode 100644 RefactorThis.Persistence/repositories/InvoiceRepository.cs diff --git a/RefactorThis.Domain.Tests/InvoicePaymentProcessorTests.cs b/RefactorThis.Domain.Tests/InvoicePaymentProcessorTests.cs index 3a607fd..ee22115 100644 --- a/RefactorThis.Domain.Tests/InvoicePaymentProcessorTests.cs +++ b/RefactorThis.Domain.Tests/InvoicePaymentProcessorTests.cs @@ -1,247 +1,248 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using RefactorThis.Persistence; +using RefactorThis.Domain.common; +using RefactorThis.Domain.common.enums; +using RefactorThis.Persistence.models; +using RefactorThis.Persistence.repositories; namespace RefactorThis.Domain.Tests { - [TestFixture] - public class InvoicePaymentProcessorTests - { - [Test] - public void ProcessPayment_Should_ThrowException_When_NoInoiceFoundForPaymentReference( ) - { - var repo = new InvoiceRepository( ); - - Invoice invoice = null; - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ); - var failureMessage = ""; - - try - { - var result = paymentProcessor.ProcessPayment( payment ); - } - catch ( InvalidOperationException e ) - { - failureMessage = e.Message; - } - - Assert.AreEqual( "There is no invoice matching this payment", failureMessage ); - } - - [Test] - public void ProcessPayment_Should_ReturnFailureMessage_When_NoPaymentNeeded( ) - { - var repo = new InvoiceRepository( ); - - var invoice = new Invoice( repo ) - { - Amount = 0, - AmountPaid = 0, - Payments = null - }; - - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ); - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "no payment needed", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnFailureMessage_When_InvoiceAlreadyFullyPaid( ) - { - var repo = new InvoiceRepository( ); - - var invoice = new Invoice( repo ) - { - Amount = 10, - AmountPaid = 10, - Payments = new List - { - new Payment - { - Amount = 10 - } - } - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ); - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "invoice was already fully paid", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnFailureMessage_When_PartialPaymentExistsAndAmountPaidExceedsAmountDue( ) - { - var repo = new InvoiceRepository( ); - var invoice = new Invoice( repo ) - { - Amount = 10, - AmountPaid = 5, - Payments = new List - { - new Payment - { - Amount = 5 - } - } - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ) - { - Amount = 6 - }; - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "the payment is greater than the partial amount remaining", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnFailureMessage_When_NoPartialPaymentExistsAndAmountPaidExceedsInvoiceAmount( ) - { - var repo = new InvoiceRepository( ); - var invoice = new Invoice( repo ) - { - Amount = 5, - AmountPaid = 0, - Payments = new List( ) - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ) - { - Amount = 6 - }; - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "the payment is greater than the invoice amount", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnFullyPaidMessage_When_PartialPaymentExistsAndAmountPaidEqualsAmountDue( ) - { - var repo = new InvoiceRepository( ); - var invoice = new Invoice( repo ) - { - Amount = 10, - AmountPaid = 5, - Payments = new List - { - new Payment - { - Amount = 5 - } - } - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ) - { - Amount = 5 - }; - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "final partial payment received, invoice is now fully paid", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnFullyPaidMessage_When_NoPartialPaymentExistsAndAmountPaidEqualsInvoiceAmount( ) - { - var repo = new InvoiceRepository( ); - var invoice = new Invoice( repo ) - { - Amount = 10, - AmountPaid = 0, - Payments = new List( ) { new Payment( ) { Amount = 10 } } - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ) - { - Amount = 10 - }; - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "invoice was already fully paid", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnPartiallyPaidMessage_When_PartialPaymentExistsAndAmountPaidIsLessThanAmountDue( ) - { - var repo = new InvoiceRepository( ); - var invoice = new Invoice( repo ) - { - Amount = 10, - AmountPaid = 5, - Payments = new List - { - new Payment - { - Amount = 5 - } - } - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ) - { - Amount = 1 - }; - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "another partial payment received, still not fully paid", result ); - } - - [Test] - public void ProcessPayment_Should_ReturnPartiallyPaidMessage_When_NoPartialPaymentExistsAndAmountPaidIsLessThanInvoiceAmount( ) - { - var repo = new InvoiceRepository( ); - var invoice = new Invoice( repo ) - { - Amount = 10, - AmountPaid = 0, - Payments = new List( ) - }; - repo.Add( invoice ); - - var paymentProcessor = new InvoiceService( repo ); - - var payment = new Payment( ) - { - Amount = 1 - }; - - var result = paymentProcessor.ProcessPayment( payment ); - - Assert.AreEqual( "invoice is now partially paid", result ); - } - } + [TestFixture] + public class InvoicePaymentProcessorTests + { + [Test] + public void ProcessPayment_Should_ThrowException_When_NoInvoiceFoundForPaymentReference() + { + var repo = new InvoiceRepository(); + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment(); + var failureMessage = ""; + + try + { + paymentProcessor.ProcessPayment(payment); + } + catch (InvalidOperationException e) + { + failureMessage = e.Message; + } + + Assert.AreEqual(ProcessPaymentExceptionMessage.NoInvoiceMatchingPayment, failureMessage); + } + + [Test] + public void ProcessPayment_Should_ReturnFailureMessage_When_NoPaymentNeeded() + { + var repo = new InvoiceRepository(); + + var invoice = new Invoice() + { + Amount = 0, + AmountPaid = 0, + Payments = null + }; + + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment(); + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.NoPaymentNeeded, result); + } + + [Test] + public void ProcessPayment_Should_ReturnFailureMessage_When_InvoiceAlreadyFullyPaid() + { + var repo = new InvoiceRepository(); + + var invoice = new Invoice() + { + Amount = 10, + AmountPaid = 10, + Payments = new List + { + new Payment + { + Amount = 10 + } + } + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment(); + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.InvoiceAlreadyFullyPaid, result); + } + + [Test] + public void ProcessPayment_Should_ReturnFailureMessage_When_PartialPaymentExistsAndAmountPaidExceedsAmountDue() + { + var repo = new InvoiceRepository(); + var invoice = new Invoice() + { + Amount = 10, + AmountPaid = 5, + Payments = new List + { + new Payment + { + Amount = 5 + } + } + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment() + { + Amount = 6 + }; + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidExceedsAmountDue, result); + } + + [Test] + public void ProcessPayment_Should_ReturnFailureMessage_When_NoPartialPaymentExistsAndAmountPaidExceedsInvoiceAmount() + { + var repo = new InvoiceRepository(); + var invoice = new Invoice() + { + Amount = 5, + AmountPaid = 0, + Payments = new List() + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment() + { + Amount = 6 + }; + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.NoPartialPaymentExistsAndAmountPaidExceedsInvoiceAmount, result); + } + + [Test] + public void ProcessPayment_Should_ReturnFullyPaidMessage_When_PartialPaymentExistsAndAmountPaidEqualsAmountDue() + { + var repo = new InvoiceRepository(); + var invoice = new Invoice() + { + Amount = 10, + AmountPaid = 5, + Payments = new List + { + new Payment + { + Amount = 5 + } + } + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment() + { + Amount = 5 + }; + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidEqualsAmountDue, result); + } + + [Test] + public void ProcessPayment_Should_ReturnFullyPaidMessage_When_NoPartialPaymentExistsAndAmountPaidEqualsInvoiceAmount() + { + var repo = new InvoiceRepository(); + var invoice = new Invoice() + { + Amount = 10, + AmountPaid = 0, + Payments = new List() { new Payment() { Amount = 10 } } + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment() + { + Amount = 10 + }; + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.InvoiceAlreadyFullyPaid, result); + } + + [Test] + public void ProcessPayment_Should_ReturnPartiallyPaidMessage_When_PartialPaymentExistsAndAmountPaidIsLessThanAmountDue() + { + var repo = new InvoiceRepository(); + var invoice = new Invoice() + { + Amount = 10, + AmountPaid = 5, + Payments = new List + { + new Payment + { + Amount = 5 + } + } + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment() + { + Amount = 1 + }; + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidIsLessThanAmountDue, result); + } + + [Test] + public void ProcessPayment_Should_ReturnPartiallyPaidMessage_When_NoPartialPaymentExistsAndAmountPaidIsLessThanInvoiceAmount() + { + var repo = new InvoiceRepository(); + var invoice = new Invoice() + { + Amount = 10, + AmountPaid = 0, + Payments = new List() + }; + repo.Add(invoice); + + var paymentProcessor = new InvoiceService(repo); + + var payment = new Payment() + { + Amount = 1 + }; + + var result = paymentProcessor.ProcessPayment(payment); + + Assert.AreEqual(ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidIsLessThanAmountDue, result); + } + } } \ No newline at end of file diff --git a/RefactorThis.Domain.Tests/RefactorThis.Domain.Tests.csproj b/RefactorThis.Domain.Tests/RefactorThis.Domain.Tests.csproj index f118007..a7a3384 100644 --- a/RefactorThis.Domain.Tests/RefactorThis.Domain.Tests.csproj +++ b/RefactorThis.Domain.Tests/RefactorThis.Domain.Tests.csproj @@ -1,67 +1,80 @@  - - - Debug - AnyCPU - {7971BDEC-EAD1-4FB8-A4F5-B1F67E4F6355} - {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - Properties - RefactorThis.Domain.Tests - RefactorThis.Domain.Tests - v4.7.2 - 512 - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll - - - - - - - - - {5310b2fe-e26d-414e-b656-1f74c5a70368} - RefactorThis.Domain - - - {33cdc796-ff75-449c-9637-59c2efc46361} - RefactorThis.Persistence - - - - - - + \ No newline at end of file diff --git a/RefactorThis.Domain/InvoiceService.cs b/RefactorThis.Domain/InvoiceService.cs index fbd674c..f9b07ee 100644 --- a/RefactorThis.Domain/InvoiceService.cs +++ b/RefactorThis.Domain/InvoiceService.cs @@ -1,149 +1,97 @@ using System; using System.Linq; -using RefactorThis.Persistence; +using RefactorThis.Domain.common; +using RefactorThis.Domain.common.enums; +using RefactorThis.Persistence.enums; +using RefactorThis.Persistence.models; +using RefactorThis.Persistence.repositories; namespace RefactorThis.Domain { - public class InvoiceService - { - private readonly InvoiceRepository _invoiceRepository; + public class InvoiceService + { + private readonly IInvoiceRepository _invoiceRepository; + private const decimal TaxRate = 0.14m; - public InvoiceService( InvoiceRepository invoiceRepository ) - { - _invoiceRepository = invoiceRepository; - } + public InvoiceService(IInvoiceRepository invoiceRepository) + { + _invoiceRepository = invoiceRepository; + } + + /// + /// Processes a payment by applying it to the matching invoice if valid. + /// + /// The payment information to be applied to an invoice. + /// + /// A indicating the result of the operation, + /// such as full payment, partial payment, overpayment, or invoice not found. + /// + /// + /// Thrown if no invoice matches the payment reference or the invoice is in an invalid state. + /// + public ProcessPaymentStatus ProcessPayment(Payment payment) + { + var invoice = _invoiceRepository.GetByReference(payment.Reference) ?? + throw new InvalidOperationException(ProcessPaymentExceptionMessage.NoInvoiceMatchingPayment); + + if (invoice.Amount == 0) + { + if (invoice.Payments == null || !invoice.Payments.Any()) + { + return ProcessPaymentStatus.NoPaymentNeeded; + } - public string ProcessPayment( Payment payment ) - { - var inv = _invoiceRepository.GetInvoice( payment.Reference ); + throw new InvalidOperationException(ProcessPaymentExceptionMessage.InvalidInvoiceState); + } - var responseMessage = string.Empty; + var totalPaid = invoice.Payments?.Sum(x => x.Amount) ?? 0; + var remaining = invoice.Amount - invoice.AmountPaid; - if ( inv == null ) - { - throw new InvalidOperationException( "There is no invoice matching this payment" ); - } - else - { - if ( inv.Amount == 0 ) - { - if ( inv.Payments == null || !inv.Payments.Any( ) ) - { - responseMessage = "no payment needed"; - } - else - { - throw new InvalidOperationException( "The invoice is in an invalid state, it has an amount of 0 and it has payments." ); - } - } - else - { - if ( inv.Payments != null && inv.Payments.Any( ) ) - { - if ( inv.Payments.Sum( x => x.Amount ) != 0 && inv.Amount == inv.Payments.Sum( x => x.Amount ) ) - { - responseMessage = "invoice was already fully paid"; - } - else if ( inv.Payments.Sum( x => x.Amount ) != 0 && payment.Amount > ( inv.Amount - inv.AmountPaid ) ) - { - responseMessage = "the payment is greater than the partial amount remaining"; - } - else - { - if ( ( inv.Amount - inv.AmountPaid ) == payment.Amount ) - { - switch ( inv.Type ) - { - case InvoiceType.Standard: - inv.AmountPaid += payment.Amount; - inv.Payments.Add( payment ); - responseMessage = "final partial payment received, invoice is now fully paid"; - break; - case InvoiceType.Commercial: - inv.AmountPaid += payment.Amount; - inv.TaxAmount += payment.Amount * 0.14m; - inv.Payments.Add( payment ); - responseMessage = "final partial payment received, invoice is now fully paid"; - break; - default: - throw new ArgumentOutOfRangeException( ); - } - - } - else - { - switch ( inv.Type ) - { - case InvoiceType.Standard: - inv.AmountPaid += payment.Amount; - inv.Payments.Add( payment ); - responseMessage = "another partial payment received, still not fully paid"; - break; - case InvoiceType.Commercial: - inv.AmountPaid += payment.Amount; - inv.TaxAmount += payment.Amount * 0.14m; - inv.Payments.Add( payment ); - responseMessage = "another partial payment received, still not fully paid"; - break; - default: - throw new ArgumentOutOfRangeException( ); - } - } - } - } - else - { - if ( payment.Amount > inv.Amount ) - { - responseMessage = "the payment is greater than the invoice amount"; - } - else if ( inv.Amount == payment.Amount ) - { - switch ( inv.Type ) - { - case InvoiceType.Standard: - inv.AmountPaid = payment.Amount; - inv.TaxAmount = payment.Amount * 0.14m; - inv.Payments.Add( payment ); - responseMessage = "invoice is now fully paid"; - break; - case InvoiceType.Commercial: - inv.AmountPaid = payment.Amount; - inv.TaxAmount = payment.Amount * 0.14m; - inv.Payments.Add( payment ); - responseMessage = "invoice is now fully paid"; - break; - default: - throw new ArgumentOutOfRangeException( ); - } - } - else - { - switch ( inv.Type ) - { - case InvoiceType.Standard: - inv.AmountPaid = payment.Amount; - inv.TaxAmount = payment.Amount * 0.14m; - inv.Payments.Add( payment ); - responseMessage = "invoice is now partially paid"; - break; - case InvoiceType.Commercial: - inv.AmountPaid = payment.Amount; - inv.TaxAmount = payment.Amount * 0.14m; - inv.Payments.Add( payment ); - responseMessage = "invoice is now partially paid"; - break; - default: - throw new ArgumentOutOfRangeException( ); - } - } - } - } - } - - inv.Save(); + if (totalPaid >= invoice.Amount) + { + return ProcessPaymentStatus.InvoiceAlreadyFullyPaid; + } - return responseMessage; - } - } + if (totalPaid > 0 && payment.Amount > remaining) + { + return ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidExceedsAmountDue; + } + + if (totalPaid == 0 && payment.Amount > invoice.Amount) + { + return ProcessPaymentStatus.NoPartialPaymentExistsAndAmountPaidExceedsInvoiceAmount; + } + + var isFullPayment = payment.Amount == remaining; + + ApplyPayment(invoice, payment, isFullPayment); + + return totalPaid == 0 + ? isFullPayment + ? ProcessPaymentStatus.InvoiceAlreadyFullyPaid + : ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidIsLessThanAmountDue + : isFullPayment + ? ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidEqualsAmountDue + : ProcessPaymentStatus.PartialPaymentExistsAndAmountPaidIsLessThanAmountDue; + } + + /// + /// Applies a payment to the given invoice and updates tax if applicable. + /// + /// The invoice to apply the payment to. + /// The payment details. + /// Indicates whether tax should be applied for this payment. + private void ApplyPayment(Invoice invoice, Payment payment, bool applyTax) + { + invoice.AmountPaid += payment.Amount; + invoice.Payments.Add(payment); + + if (invoice.Type == InvoiceType.Commercial || applyTax) + { + invoice.TaxAmount += payment.Amount * TaxRate; + } + + _invoiceRepository.Update(invoice); + } + } } \ No newline at end of file diff --git a/RefactorThis.Domain/RefactorThis.Domain.csproj b/RefactorThis.Domain/RefactorThis.Domain.csproj index 753e893..7219765 100644 --- a/RefactorThis.Domain/RefactorThis.Domain.csproj +++ b/RefactorThis.Domain/RefactorThis.Domain.csproj @@ -1,59 +1,105 @@  - - - Debug - AnyCPU - {5310B2FE-E26D-414E-B656-1F74C5A70368} - Library - Properties - RefactorThis.Domain - RefactorThis.Domain - v4.7.2 - 512 - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - {33cdc796-ff75-449c-9637-59c2efc46361} - RefactorThis.Persistence - - - - - - + \ No newline at end of file diff --git a/RefactorThis.Domain/common/ProcessPaymentExceptionMessage.cs b/RefactorThis.Domain/common/ProcessPaymentExceptionMessage.cs new file mode 100644 index 0000000..3c56ab1 --- /dev/null +++ b/RefactorThis.Domain/common/ProcessPaymentExceptionMessage.cs @@ -0,0 +1,8 @@ +namespace RefactorThis.Domain.common +{ + public abstract class ProcessPaymentExceptionMessage + { + public const string NoInvoiceMatchingPayment = "There is no invoice matching this payment."; + public const string InvalidInvoiceState = "The invoice is in an invalid state, it has an amount of 0 and it has payments."; + } +} \ No newline at end of file diff --git a/RefactorThis.Domain/common/enums/ProcessPaymentStatus.cs b/RefactorThis.Domain/common/enums/ProcessPaymentStatus.cs new file mode 100644 index 0000000..4af3586 --- /dev/null +++ b/RefactorThis.Domain/common/enums/ProcessPaymentStatus.cs @@ -0,0 +1,18 @@ +namespace RefactorThis.Domain.common.enums +{ + public enum ProcessPaymentStatus + { + // "No payment needed"; + NoPaymentNeeded, + // "Invoice was already fully paid"; + InvoiceAlreadyFullyPaid, + // "The payment is greater than the partial amount remaining"; + PartialPaymentExistsAndAmountPaidExceedsAmountDue, + // "The payment is greater than the invoice amount"; + NoPartialPaymentExistsAndAmountPaidExceedsInvoiceAmount, + // "Another partial payment received, still not fully paid"; + PartialPaymentExistsAndAmountPaidIsLessThanAmountDue, + // "Final partial payment received, invoice is now fully paid"; + PartialPaymentExistsAndAmountPaidEqualsAmountDue + } +} \ No newline at end of file diff --git a/RefactorThis.Persistence/Invoice.cs b/RefactorThis.Persistence/Invoice.cs deleted file mode 100644 index bd4370d..0000000 --- a/RefactorThis.Persistence/Invoice.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; - -namespace RefactorThis.Persistence -{ - public class Invoice - { - private readonly InvoiceRepository _repository; - public Invoice( InvoiceRepository repository ) - { - _repository = repository; - } - - public void Save( ) - { - _repository.SaveInvoice( this ); - } - - public decimal Amount { get; set; } - public decimal AmountPaid { get; set; } - public decimal TaxAmount { get; set; } - public List Payments { get; set; } - - public InvoiceType Type { get; set; } - } - - public enum InvoiceType - { - Standard, - Commercial - } -} \ No newline at end of file diff --git a/RefactorThis.Persistence/InvoiceRepository.cs b/RefactorThis.Persistence/InvoiceRepository.cs deleted file mode 100644 index 38548c7..0000000 --- a/RefactorThis.Persistence/InvoiceRepository.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace RefactorThis.Persistence { - public class InvoiceRepository - { - private Invoice _invoice; - - public Invoice GetInvoice( string reference ) - { - return _invoice; - } - - public void SaveInvoice( Invoice invoice ) - { - //saves the invoice to the database - } - - public void Add( Invoice invoice ) - { - _invoice = invoice; - } - } -} \ No newline at end of file diff --git a/RefactorThis.Persistence/Payment.cs b/RefactorThis.Persistence/Payment.cs deleted file mode 100644 index db29372..0000000 --- a/RefactorThis.Persistence/Payment.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace RefactorThis.Persistence -{ - public class Payment - { - public decimal Amount { get; set; } - public string Reference { get; set; } - } -} \ No newline at end of file diff --git a/RefactorThis.Persistence/enums/InvoiceType.cs b/RefactorThis.Persistence/enums/InvoiceType.cs new file mode 100644 index 0000000..01a8786 --- /dev/null +++ b/RefactorThis.Persistence/enums/InvoiceType.cs @@ -0,0 +1,8 @@ +namespace RefactorThis.Persistence.enums +{ + public enum InvoiceType + { + Standard, + Commercial + } +} \ No newline at end of file diff --git a/RefactorThis.Persistence/models/Invoice.cs b/RefactorThis.Persistence/models/Invoice.cs new file mode 100644 index 0000000..66f8999 --- /dev/null +++ b/RefactorThis.Persistence/models/Invoice.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using RefactorThis.Persistence.enums; + +namespace RefactorThis.Persistence.models +{ + /// + /// Represents an invoice with details about the amount, tax, payments, and type. + /// + public class Invoice + { + /// + /// The total amount due for the invoice, before any payments or taxes. + /// + public decimal Amount { get; set; } + + /// + /// The total amount that has been paid towards the invoice. + /// + public decimal AmountPaid { get; set; } + + /// + /// The amount of tax included in the invoice. + /// + public decimal TaxAmount { get; set; } + + /// + /// A list of individual payments made towards the invoice. + /// + public List Payments { get; set; } + + /// + /// The type of the invoice (Standard, Commercial) + /// + public InvoiceType Type { get; set; } + } +} \ No newline at end of file diff --git a/RefactorThis.Persistence/models/Payment.cs b/RefactorThis.Persistence/models/Payment.cs new file mode 100644 index 0000000..d3b5547 --- /dev/null +++ b/RefactorThis.Persistence/models/Payment.cs @@ -0,0 +1,18 @@ +namespace RefactorThis.Persistence.models +{ + /// + /// Represents a payment made towards an invoice. + /// + public class Payment + { + /// + /// The amount of money paid in this payment transaction. + /// + public decimal Amount { get; set; } + + /// + /// A reference or identifier for the payment (e.g., transaction ID, check number). + /// + public string Reference { get; set; } + } +} \ No newline at end of file diff --git a/RefactorThis.Persistence/repositories/IInvoiceRepository.cs b/RefactorThis.Persistence/repositories/IInvoiceRepository.cs new file mode 100644 index 0000000..8ed73c2 --- /dev/null +++ b/RefactorThis.Persistence/repositories/IInvoiceRepository.cs @@ -0,0 +1,11 @@ +using RefactorThis.Persistence.models; + +namespace RefactorThis.Persistence.repositories +{ + public interface IInvoiceRepository + { + Invoice GetByReference(string reference); + void Update(Invoice invoice); + void Add(Invoice invoice); + } +} diff --git a/RefactorThis.Persistence/repositories/InvoiceRepository.cs b/RefactorThis.Persistence/repositories/InvoiceRepository.cs new file mode 100644 index 0000000..3f8ba48 --- /dev/null +++ b/RefactorThis.Persistence/repositories/InvoiceRepository.cs @@ -0,0 +1,24 @@ +using RefactorThis.Persistence.models; + +namespace RefactorThis.Persistence.repositories +{ + public class InvoiceRepository : IInvoiceRepository + { + private Invoice _invoice; + + public Invoice GetByReference(string reference) + { + return _invoice; + } + + public void Update(Invoice invoice) + { + // saves the invoice to the database + } + + public void Add(Invoice invoice) + { + _invoice = invoice; + } + } +} \ No newline at end of file