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
119 changes: 117 additions & 2 deletions Smartwyre.DeveloperTest.Runner/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,126 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Smartwyre.DeveloperTest.Data;
using Smartwyre.DeveloperTest.Rebates.Calculators;
using Smartwyre.DeveloperTest.Rebates.Factories;
using Smartwyre.DeveloperTest.Services;
using Smartwyre.DeveloperTest.Types;

namespace Smartwyre.DeveloperTest.Runner;

class Program
{
static void Main(string[] args)
static int Main(string[] args)
{
throw new NotImplementedException();
using var serviceProvider = ConfigureServices();

var rebateService = serviceProvider.GetRequiredService<IRebateService>();
var rebateDataStore = serviceProvider.GetRequiredService<IRebateDataStore>();
var productDataStore = serviceProvider.GetRequiredService<IProductDataStore>();

Console.WriteLine("This runner prompts for rebate input values and calculates the rebate.");
Console.WriteLine("Provide the rebate identifier, product identifier, and volume when prompted.");

ShowAvailableProducts(productDataStore);
ShowAvailableRebates(rebateDataStore);

var request = BuildRequest();
if (request == null)
{
Console.WriteLine("Invalid input. Exiting.");
return 1;
}

try
{
var result = rebateService.Calculate(request);
Console.WriteLine();
Console.WriteLine("Rebate calculation result:");
Console.WriteLine(result.Success ? " - Success" : " - No rebate was calculated for the provided request");
Console.WriteLine();
Console.WriteLine("Request details:");
Console.WriteLine($" Rebate Identifier: {request.RebateIdentifier}");
Console.WriteLine($" Product Identifier: {request.ProductIdentifier}");
Console.WriteLine($" Volume: {request.Volume}");
return result.Success ? 0 : 2;
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
return 1;
}
}

private static CalculateRebateRequest BuildRequest()
{
Console.WriteLine("Enter rebate details to calculate a rebate.");
Console.WriteLine("Press Enter without typing to cancel.");

var rebateIdentifier = Prompt("Rebate Identifier");
var productIdentifier = Prompt("Product Identifier");
var volumeInput = Prompt("Volume");

if (string.IsNullOrWhiteSpace(rebateIdentifier) || string.IsNullOrWhiteSpace(productIdentifier) || string.IsNullOrWhiteSpace(volumeInput))
{
Console.WriteLine("Rebate identifier, product identifier, and volume are required.");
return null;
}

if (!decimal.TryParse(volumeInput, out var volume))
{
Console.WriteLine($"Invalid volume '{volumeInput}'. Please provide a numeric value.");
return null;
}

return new CalculateRebateRequest
{
RebateIdentifier = rebateIdentifier,
ProductIdentifier = productIdentifier,
Volume = volume
};
}

private static string Prompt(string label)
{
Console.Write(label + ": ");
return Console.ReadLine() ?? string.Empty;
}

private static void ShowAvailableProducts(IProductDataStore productDataStore)
{
Console.WriteLine();
Console.WriteLine("Available products:");
foreach (var product in productDataStore.GetProducts())
{
Console.WriteLine($" - Identifier: {product.Identifier}, Price: {product.Price:C}, UOM: {product.Uom}, Supported incentives: {product.SupportedIncentives}");
}
Console.WriteLine();
}

private static void ShowAvailableRebates(IRebateDataStore rebateDataStore)
{
Console.WriteLine("Available rebates:");
foreach (var rebate in rebateDataStore.GetRebates())
{
Console.WriteLine($" - Identifier: {rebate.Identifier}, Incentive: {rebate.Incentive.ToString()}, Amount: { rebate.Amount:C}, Percentage: {rebate.Percentage}");
}
Console.WriteLine();
}

private static ServiceProvider ConfigureServices()
{
var services = new ServiceCollection();

services.AddScoped<IRebateService, RebateService>();
services.AddScoped<IRebateDataStore, RebateDataStore>();
services.AddScoped<IProductDataStore, ProductDataStore>();

services.AddScoped<IRebateCalculator, FixedCashAmountCalculator>();
services.AddScoped<IRebateCalculator, FixedRateRebateCalculator>();
services.AddScoped<IRebateCalculator, AmountPerUomCalculator>();
services.AddScoped<IRebateCalculatorFactory, RebateCalculatorFactory>();

return services.BuildServiceProvider();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Smartwyre.DeveloperTest\Smartwyre.DeveloperTest.csproj" />
</ItemGroup>

</Project>
13 changes: 0 additions & 13 deletions Smartwyre.DeveloperTest.Tests/PaymentService.Tests.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
using Smartwyre.DeveloperTest.Rebates.Calculators;
using Smartwyre.DeveloperTest.Types;
using Xunit;

namespace Smartwyre.DeveloperTest.Tests.Rebates.Calculators;

public class FixedCashAmountCalculatorTests
{
private readonly FixedCashAmountCalculator _calculator = new();

[Fact]
public void CanCalculate_ReturnsTrue_WhenProductSupportsIncentiveAndAmountIsPositive()
{
var rebate = new Rebate { Amount = 25m };
var product = new Product { SupportedIncentives = SupportedIncentiveType.FixedCashAmount };

Assert.True(_calculator.CanCalculate(rebate, product, new CalculateRebateRequest()));
}

[Theory]
[InlineData(0)]
[InlineData(-1)]
public void CanCalculate_ReturnsFalse_WhenAmountIsNotPositive(decimal amount)
{
var rebate = new Rebate { Amount = amount };
var product = new Product { SupportedIncentives = SupportedIncentiveType.FixedCashAmount };

Assert.False(_calculator.CanCalculate(rebate, product, new CalculateRebateRequest()));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenRebateIsNull()
{
var product = new Product { SupportedIncentives = SupportedIncentiveType.FixedCashAmount };

Assert.False(_calculator.CanCalculate(null!, product, new CalculateRebateRequest()));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenProductIsNull()
{
var rebate = new Rebate { Amount = 25m };

Assert.False(_calculator.CanCalculate(rebate, null!, new CalculateRebateRequest()));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenProductDoesNotSupportIncentive()
{
var rebate = new Rebate { Amount = 25m };
var product = new Product { SupportedIncentives = SupportedIncentiveType.FixedRateRebate };

Assert.False(_calculator.CanCalculate(rebate, product, new CalculateRebateRequest()));
}

[Fact]
public void Calculate_ReturnsRebateAmount()
{
var rebate = new Rebate { Amount = 25m };

var result = _calculator.Calculate(rebate, new Product(), new CalculateRebateRequest());

Assert.Equal(25m, result);
}
}

public class FixedRateRebateCalculatorTests
{
private readonly FixedRateRebateCalculator _calculator = new();

[Fact]
public void CanCalculate_ReturnsTrue_WhenAllInputsAreValid()
{
var rebate = new Rebate { Percentage = 0.1m };
var product = new Product
{
Price = 100m,
SupportedIncentives = SupportedIncentiveType.FixedRateRebate
};
var request = new CalculateRebateRequest { Volume = 5m };

Assert.True(_calculator.CanCalculate(rebate, product, request));
}

[Theory]
[InlineData(0, 100, 5)]
[InlineData(0.1, 0, 5)]
[InlineData(0.1, 100, 0)]
public void CanCalculate_ReturnsFalse_WhenPercentagePriceOrVolumeIsZero(
decimal percentage, decimal price, decimal volume)
{
var rebate = new Rebate { Percentage = percentage };
var product = new Product
{
Price = price,
SupportedIncentives = SupportedIncentiveType.FixedRateRebate
};
var request = new CalculateRebateRequest { Volume = volume };

Assert.False(_calculator.CanCalculate(rebate, product, request));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenRebateIsNull()
{
var product = new Product
{
Price = 100m,
SupportedIncentives = SupportedIncentiveType.FixedRateRebate
};
var request = new CalculateRebateRequest { Volume = 5m };

Assert.False(_calculator.CanCalculate(null!, product, request));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenProductIsNull()
{
var rebate = new Rebate { Percentage = 0.1m };
var request = new CalculateRebateRequest { Volume = 5m };

Assert.False(_calculator.CanCalculate(rebate, null!, request));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenProductDoesNotSupportIncentive()
{
var rebate = new Rebate { Percentage = 0.1m };
var product = new Product
{
Price = 100m,
SupportedIncentives = SupportedIncentiveType.FixedCashAmount
};
var request = new CalculateRebateRequest { Volume = 5m };

Assert.False(_calculator.CanCalculate(rebate, product, request));
}

[Fact]
public void Calculate_ReturnsPriceTimesPercentageTimesVolume()
{
var rebate = new Rebate { Percentage = 0.1m };
var product = new Product { Price = 100m };
var request = new CalculateRebateRequest { Volume = 5m };

var result = _calculator.Calculate(rebate, product, request);

Assert.Equal(50m, result);
}
}

public class AmountPerUomCalculatorTests
{
private readonly AmountPerUomCalculator _calculator = new();

[Fact]
public void CanCalculate_ReturnsTrue_WhenAllInputsAreValid()
{
var rebate = new Rebate { Amount = 5m };
var product = new Product { SupportedIncentives = SupportedIncentiveType.AmountPerUom };
var request = new CalculateRebateRequest { Volume = 10m };

Assert.True(_calculator.CanCalculate(rebate, product, request));
}

[Theory]
[InlineData(0, 10)]
[InlineData(5, 0)]
public void CanCalculate_ReturnsFalse_WhenAmountOrVolumeIsZero(decimal amount, decimal volume)
{
var rebate = new Rebate { Amount = amount };
var product = new Product { SupportedIncentives = SupportedIncentiveType.AmountPerUom };
var request = new CalculateRebateRequest { Volume = volume };

Assert.False(_calculator.CanCalculate(rebate, product, request));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenRebateIsNull()
{
var product = new Product { SupportedIncentives = SupportedIncentiveType.AmountPerUom };
var request = new CalculateRebateRequest { Volume = 10m };

Assert.False(_calculator.CanCalculate(null!, product, request));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenProductIsNull()
{
var rebate = new Rebate { Amount = 5m };
var request = new CalculateRebateRequest { Volume = 10m };

Assert.False(_calculator.CanCalculate(rebate, null!, request));
}

[Fact]
public void CanCalculate_ReturnsFalse_WhenProductDoesNotSupportIncentive()
{
var rebate = new Rebate { Amount = 5m };
var product = new Product { SupportedIncentives = SupportedIncentiveType.FixedCashAmount };
var request = new CalculateRebateRequest { Volume = 10m };

Assert.False(_calculator.CanCalculate(rebate, product, request));
}

[Fact]
public void Calculate_ReturnsAmountTimesVolume()
{
var rebate = new Rebate { Amount = 5m };
var request = new CalculateRebateRequest { Volume = 10m };

var result = _calculator.Calculate(rebate, new Product(), request);

Assert.Equal(50m, result);
}
}
Loading