Content is user-generated and unverified.
// Models/CommissionModels.cs using System.Collections.Generic; namespace CommissionScheme.Models { public class Agent { public int Id { get; set; } public string Name { get; set; } public string Role { get; set; } public int? ParentId { get; set; } public List<Agent> Children { get; set; } = new List<Agent>(); } public class CommissionStructure { public string Title { get; set; } public string Structure { get; set; } public decimal GrossPercentage { get; set; } public decimal NetPercentage { get; set; } } public class CommissionCalculationResult { public int AgentId { get; set; } public string AgentName { get; set; } public string Role { get; set; } public decimal GrossAmount { get; set; } public decimal NetAmount { get; set; } public decimal SaleAmount { get; set; } } public class Sale { public int Id { get; set; } public int AgentId { get; set; } public decimal Amount { get; set; } public DateTime Date { get; set; } } } // Services/CommissionCalculatorService.cs using CommissionScheme.Models; using System.Collections.Generic; using System.Linq; namespace CommissionScheme.Services { public enum CommissionScenario { Scenario1, Scenario2 } public class CommissionCalculatorService { private readonly Dictionary<CommissionScenario, Dictionary<string, CommissionStructure>> _commissionScenarios; public CommissionCalculatorService() { _commissionScenarios = new Dictionary<CommissionScenario, Dictionary<string, CommissionStructure>> { { CommissionScenario.Scenario1, new Dictionary<string, CommissionStructure> { { "Agent", new CommissionStructure { Title = "Agent", Structure = "100.0%", GrossPercentage = 65.0m, NetPercentage = 65.0m } }, { "TL", new CommissionStructure { Title = "TL", Structure = "40.0%", GrossPercentage = 4.8m, NetPercentage = 1.92m } }, { "HOT", new CommissionStructure { Title = "HOT", Structure = "60.0%", GrossPercentage = 0, NetPercentage = 2.88m } }, { "DOS", new CommissionStructure { Title = "DOS", Structure = "1/3 of (DOS+VP)", GrossPercentage = 5.0m, NetPercentage = 3.33m } }, { "VP", new CommissionStructure { Title = "VP", Structure = "1/3 of (DOS+VP)", GrossPercentage = 5.0m, NetPercentage = 3.33m } }, { "RGR", new CommissionStructure { Title = "RGR", Structure = "100.0%", GrossPercentage = 2.5m, NetPercentage = 2.5m } }, { "PIC", new CommissionStructure { Title = "PIC", Structure = "100.0%", GrossPercentage = 1.7m, NetPercentage = 1.7m } } } }, { CommissionScenario.Scenario2, new Dictionary<string, CommissionStructure> { { "Agent", new CommissionStructure { Title = "Agent", Structure = "100.0%", GrossPercentage = 65.0m, NetPercentage = 65.0m } }, { "TL", new CommissionStructure { Title = "TL", Structure = "40.0%", GrossPercentage = 4.8m, NetPercentage = 1.92m } }, { "HOT", new CommissionStructure { Title = "HOT", Structure = "60.0%", GrossPercentage = 0, NetPercentage = 2.88m } }, { "DOS", new CommissionStructure { Title = "DOS", Structure = "1/3 of (DOS+VP)", GrossPercentage = 5.0m, NetPercentage = 2.53m } }, { "VP", new CommissionStructure { Title = "VP", Structure = "1/3 of (DOS+VP)", GrossPercentage = 5.0m, NetPercentage = 2.53m } }, { "RGR", new CommissionStructure { Title = "RGR", Structure = "100.0%", GrossPercentage = 2.5m, NetPercentage = 2.5m } }, { "PIC", new CommissionStructure { Title = "PIC", Structure = "100.0%", GrossPercentage = 1.7m, NetPercentage = 1.7m } } } } }; } public List<CommissionCalculationResult> CalculateCommissions(List<Agent> hierarchy, Sale sale, CommissionScenario scenario = CommissionScenario.Scenario1) { var results = new List<CommissionCalculationResult>(); var saleAgent = FindAgentById(hierarchy, sale.AgentId); if (saleAgent == null) return results; // Get the path from sale agent to root var agentPath = GetAgentPath(hierarchy, saleAgent); var commissionStructures = _commissionScenarios[scenario]; foreach (var agent in agentPath) { if (commissionStructures.TryGetValue(agent.Role, out var structure)) { var grossAmount = (sale.Amount * structure.GrossPercentage) / 100; var netAmount = (sale.Amount * structure.NetPercentage) / 100; results.Add(new CommissionCalculationResult { AgentId = agent.Id, AgentName = agent.Name, Role = agent.Role, GrossAmount = grossAmount, NetAmount = netAmount, SaleAmount = sale.Amount }); } } return results; } private Agent FindAgentById(List<Agent> hierarchy, int agentId) { foreach (var agent in hierarchy) { if (agent.Id == agentId) return agent; var found = FindAgentById(agent.Children, agentId); if (found != null) return found; } return null; } private List<Agent> GetAgentPath(List<Agent> hierarchy, Agent targetAgent) { var path = new List<Agent>(); var current = targetAgent; while (current != null) { path.Add(current); current = FindParent(hierarchy, current); } return path; } private Agent FindParent(List<Agent> hierarchy, Agent child) { if (child.ParentId == null) return null; foreach (var agent in hierarchy) { if (agent.Id == child.ParentId) return agent; var found = FindParent(agent.Children, child); if (found != null) return found; } return null; } public decimal CalculateTotalCommission(List<CommissionCalculationResult> results) { return results.Sum(r => r.NetAmount); } } } // Features/CommissionCalculation.feature Feature: Commission Calculation As a sales manager I want to calculate commissions for agents based on their hierarchy So that I can ensure proper commission distribution Background: Given the following agent hierarchy exists: | Id | Name | Role | ParentId | | 1 | Company | PIC | | | 17 | Aaron Siow | VP | 1 | | 11770 | Lee Zi Han | HOT | 17 | | 223681| Kuhen | TL | 11770 | | 227219| Lankas Ravindran| Agent| 223681 | | 246499| A. Mohan | Agent| 227219 | Scenario: Calculate commission for a sale made by bottom-level agent - Scenario 1 Given I am using commission scenario 1 And a sale of $10000 is made by agent 246499 When I calculate the commissions Then the commission should be distributed as follows: | AgentName | Role | GrossAmount | NetAmount | | A. Mohan | Agent | 6500.00 | 6500.00 | | Lankas Ravindran | Agent | 6500.00 | 6500.00 | | Kuhen | TL | 480.00 | 192.00 | | Lee Zi Han | HOT | 0.00 | 288.00 | | Aaron Siow | VP | 500.00 | 333.00 | | Company | PIC | 170.00 | 170.00 | Scenario: Calculate commission for a sale made by team leader - Scenario 1 Given I am using commission scenario 1 And a sale of $5000 is made by agent 223681 When I calculate the commissions Then the commission should be distributed as follows: | AgentName | Role | GrossAmount | NetAmount | | Kuhen | TL | 240.00 | 96.00 | | Lee Zi Han | HOT | 0.00 | 144.00 | | Aaron Siow | VP | 250.00 | 166.50 | | Company | PIC | 85.00 | 85.00 | Scenario: Calculate total commission for multiple sales - Scenario 1 Given I am using commission scenario 1 And a sale of $10000 is made by agent 246499 And a sale of $5000 is made by agent 223681 When I calculate the total commissions Then the total commission amount should be $15073.50 Background: Scenario 2 Hierarchy Given the following agent hierarchy exists for scenario 2: | Id | Name | Role | ParentId | | 1 | Company | PIC | | | 17 | Regional Head | RGR | 1 | | 18 | VP Level 2 | VP2 | 17 | | 19 | VP Level 1 | VP1 | 18 | | 20 | DOS Level 5 | DOS5 | 19 | | 21 | HOT Level 3 | HOT3 | 20 | | 22 | HOT Level 2 | HOT2 | 21 | | 223681| Kuhen | TL | 22 | | 227219| Lankas Ravindran| Agent| 223681 | | 246499| A. Mohan | Agent| 227219 | Scenario: Calculate commission for a sale made by bottom-level agent - Scenario 2 Given I am using commission scenario 2 And the scenario 2 hierarchy is in place And a sale of $10000 is made by agent 246499 When I calculate the commissions Then the commission should be distributed as follows: | AgentName | Role | GrossAmount | NetAmount | | A. Mohan | Agent | 6500.00 | 6500.00 | | Lankas Ravindran | Agent | 6500.00 | 6500.00 | | Kuhen | TL | 480.00 | 192.00 | | HOT Level 2 | HOT2 | 0.00 | 288.00 | | HOT Level 3 | HOT3 | 0.00 | 240.00 | | DOS Level 5 | DOS5 | 500.00 | 253.00 | | VP Level 1 | VP1 | 500.00 | 253.00 | | VP Level 2 | VP2 | 0.00 | 253.00 | | Regional Head | RGR | 250.00 | 250.00 | | Company | PIC | 170.00 | 170.00 | Scenario: Calculate commission for a sale made by team leader - Scenario 2 Given I am using commission scenario 2 And the scenario 2 hierarchy is in place And a sale of $5000 is made by agent 223681 When I calculate the commissions Then the commission should be distributed as follows: | AgentName | Role | GrossAmount | NetAmount | | Kuhen | TL | 240.00 | 96.00 | | HOT Level 2 | HOT2 | 0.00 | 144.00 | | HOT Level 3 | HOT3 | 0.00 | 120.00 | | DOS Level 5 | DOS5 | 250.00 | 126.50 | | VP Level 1 | VP1 | 250.00 | 126.50 | | VP Level 2 | VP2 | 0.00 | 126.50 | | Regional Head| RGR | 125.00 | 125.00 | | Company | PIC | 85.00 | 85.00 | // StepDefinitions/CommissionCalculationSteps.cs using CommissionScheme.Models; using CommissionScheme.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; using Reqnroll; using System.Collections.Generic; using System.Linq; namespace CommissionScheme.StepDefinitions { [Binding] public class CommissionCalculationSteps { private List<Agent> _hierarchy; private List<Agent> _scenario2Hierarchy; private List<Sale> _sales; private List<CommissionCalculationResult> _commissionResults; private readonly CommissionCalculatorService _calculatorService; private CommissionScenario _currentScenario = CommissionScenario.Scenario1; public CommissionCalculationSteps() { _calculatorService = new CommissionCalculatorService(); _hierarchy = new List<Agent>(); _scenario2Hierarchy = new List<Agent>(); _sales = new List<Sale>(); _commissionResults = new List<CommissionCalculationResult>(); } [Given(@"I am using commission scenario (\d+)")] public void GivenIAmUsingCommissionScenario(int scenarioNumber) { _currentScenario = scenarioNumber == 1 ? CommissionScenario.Scenario1 : CommissionScenario.Scenario2; } [Given(@"the following agent hierarchy exists:")] public void GivenTheFollowingAgentHierarchyExists(Table table) { _hierarchy.Clear(); _hierarchy = BuildHierarchyFromTable(table); } [Given(@"the following agent hierarchy exists for scenario 2:")] public void GivenTheFollowingAgentHierarchyExistsForScenario2(Table table) { _scenario2Hierarchy.Clear(); _scenario2Hierarchy = BuildHierarchyFromTable(table); } [Given(@"the scenario 2 hierarchy is in place")] public void GivenTheScenario2HierarchyIsInPlace() { // Use scenario 2 hierarchy for calculations _hierarchy = _scenario2Hierarchy; } private List<Agent> BuildHierarchyFromTable(Table table) { var agents = new List<Agent>(); var hierarchy = new List<Agent>(); // Create all agents first foreach (var row in table.Rows) { var agent = new Agent { Id = int.Parse(row["Id"]), Name = row["Name"], Role = row["Role"], ParentId = string.IsNullOrEmpty(row["ParentId"]) ? (int?)null : int.Parse(row["ParentId"]) }; agents.Add(agent); } // Build hierarchy relationships foreach (var agent in agents) { if (agent.ParentId == null) { hierarchy.Add(agent); } else { var parent = agents.FirstOrDefault(a => a.Id == agent.ParentId); parent?.Children.Add(agent); } } return hierarchy; } [Given(@"a sale of \$(\d+) is made by agent (\d+)")] public void GivenASaleOfIsMadeByAgent(decimal amount, int agentId) { _sales.Add(new Sale { Id = _sales.Count + 1, AgentId = agentId, Amount = amount, Date = DateTime.Now }); } [When(@"I calculate the commissions")] public void WhenICalculateTheCommissions() { _commissionResults.Clear(); foreach (var sale in _sales) { var results = _calculatorService.CalculateCommissions(_hierarchy, sale, _currentScenario); _commissionResults.AddRange(results); } } [When(@"I calculate the total commissions")] public void WhenICalculateTheTotalCommissions() { WhenICalculateTheCommissions(); } [Then(@"the commission should be distributed as follows:")] public void ThenTheCommissionShouldBeDistributedAsFollows(Table table) { foreach (var row in table.Rows) { var agentName = row["AgentName"]; var role = row["Role"]; var expectedGross = decimal.Parse(row["GrossAmount"]); var expectedNet = decimal.Parse(row["NetAmount"]); var result = _commissionResults.FirstOrDefault(r => r.AgentName == agentName && r.Role == role); Assert.IsNotNull(result, $"Commission result not found for {agentName} ({role})"); Assert.AreEqual(expectedGross, result.GrossAmount, $"Gross amount mismatch for {agentName}"); Assert.AreEqual(expectedNet, result.NetAmount, $"Net amount mismatch for {agentName}"); } } [Then(@"the total commission amount should be \$(.*)")] public void ThenTheTotalCommissionAmountShouldBe(decimal expectedTotal) { var actualTotal = _calculatorService.CalculateTotalCommission(_commissionResults); Assert.AreEqual(expectedTotal, actualTotal, $"Expected total commission {expectedTotal}, but got {actualTotal}"); } } } // Tests/CommissionCalculatorTests.cs using CommissionScheme.Models; using CommissionScheme.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; using System.Linq; namespace CommissionScheme.Tests { [TestClass] public class CommissionCalculatorTests { private CommissionCalculatorService _service; private List<Agent> _scenario1Hierarchy; private List<Agent> _scenario2Hierarchy; [TestInitialize] public void Setup() { _service = new CommissionCalculatorService(); _scenario1Hierarchy = CreateScenario1Hierarchy(); _scenario2Hierarchy = CreateScenario2Hierarchy(); } private List<Agent> CreateScenario1Hierarchy() { var pic = new Agent { Id = 1, Name = "Company", Role = "PIC", ParentId = null }; var vp = new Agent { Id = 17, Name = "Aaron Siow", Role = "VP", ParentId = 1 }; var hot = new Agent { Id = 11770, Name = "Lee Zi Han", Role = "HOT", ParentId = 17 }; var tl = new Agent { Id = 223681, Name = "Kuhen", Role = "TL", ParentId = 11770 }; var agent1 = new Agent { Id = 227219, Name = "Lankas Ravindran", Role = "Agent", ParentId = 223681 }; var agent2 = new Agent { Id = 246499, Name = "A. Mohan", Role = "Agent", ParentId = 227219 }; pic.Children.Add(vp); vp.Children.Add(hot); hot.Children.Add(tl); tl.Children.Add(agent1); agent1.Children.Add(agent2); return new List<Agent> { pic }; } private List<Agent> CreateScenario2Hierarchy() { var pic = new Agent { Id = 1, Name = "Company", Role = "PIC", ParentId = null }; var rgr = new Agent { Id = 17, Name = "Regional Head", Role = "RGR", ParentId = 1 }; var vp2 = new Agent { Id = 18, Name = "VP Level 2", Role = "VP2", ParentId = 17 }; var vp1 = new Agent { Id = 19, Name = "VP Level 1", Role = "VP1", ParentId = 18 }; var dos5 = new Agent { Id = 20, Name = "DOS Level 5", Role = "DOS5", ParentId = 19 }; var hot3 = new Agent { Id = 21, Name = "HOT Level 3", Role = "HOT3", ParentId = 20 }; var hot2 = new Agent { Id = 22, Name = "HOT Level 2", Role = "HOT2", ParentId = 21 }; var tl = new Agent { Id = 223681, Name = "Kuhen", Role = "TL", ParentId = 22 }; var agent1 = new Agent { Id = 227219, Name = "Lankas Ravindran", Role = "Agent", ParentId = 223681 }; var agent2 = new Agent { Id = 246499, Name = "A. Mohan", Role = "Agent", ParentId = 227219 }; pic.Children.Add(rgr); rgr.Children.Add(vp2); vp2.Children.Add(vp1); vp1.Children.Add(dos5); dos5.Children.Add(hot3); hot3.Children.Add(hot2); hot2.Children.Add(tl); tl.Children.Add(agent1); agent1.Children.Add(agent2); return new List<Agent> { pic }; } [TestMethod] public void CalculateCommissions_Scenario1_ForBottomLevelAgent_ReturnsCorrectDistribution() { // Arrange var sale = new Sale { Id = 1, AgentId = 246499, Amount = 10000, Date = DateTime.Now }; // Act var results = _service.CalculateCommissions(_scenario1Hierarchy, sale, CommissionScenario.Scenario1); // Assert Assert.AreEqual(6, results.Count); var agentCommission = results.FirstOrDefault(r => r.AgentName == "A. Mohan"); Assert.IsNotNull(agentCommission); Assert.AreEqual(6500m, agentCommission.NetAmount); } [TestMethod] public void CalculateCommissions_Scenario1_ForTeamLeader_ReturnsCorrectDistribution() { // Arrange var sale = new Sale { Id = 1, AgentId = 223681, Amount = 5000, Date = DateTime.Now }; // Act var results = _service.CalculateCommissions(_scenario1Hierarchy, sale, CommissionScenario.Scenario1); // Assert Assert.AreEqual(4, results.Count); var tlCommission = results.FirstOrDefault(r => r.AgentName == "Kuhen"); Assert.IsNotNull(tlCommission); Assert.AreEqual(96m, tlCommission.NetAmount); } [TestMethod] public void CalculateCommissions_Scenario2_ForBottomLevelAgent_ReturnsCorrectDistribution() { // Arrange var sale = new Sale { Id = 1, AgentId = 246499, Amount = 10000, Date = DateTime.Now }; // Act var results = _service.CalculateCommissions(_scenario2Hierarchy, sale, CommissionScenario.Scenario2); // Assert Assert.AreEqual(10, results.Count); var agentCommission = results.FirstOrDefault(r => r.AgentName == "A. Mohan"); Assert.IsNotNull(agentCommission); Assert.AreEqual(6500m, agentCommission.NetAmount); var dos5Commission = results.FirstOrDefault(r => r.AgentName == "DOS Level 5"); Assert.IsNotNull(dos5Commission); Assert.AreEqual(253m, dos5Commission.NetAmount); } [TestMethod] public void CalculateCommissions_Scenario2_ForTeamLeader_ReturnsCorrectDistribution() { // Arrange var sale = new Sale { Id = 1, AgentId = 223681, Amount = 5000, Date = DateTime.Now }; // Act var results = _service.CalculateCommissions(_scenario2Hierarchy, sale, CommissionScenario.Scenario2); // Assert Assert.AreEqual(8, results.Count); var tlCommission = results.FirstOrDefault(r => r.AgentName == "Kuhen"); Assert.IsNotNull(tlCommission); Assert.AreEqual(96m, tlCommission.NetAmount); var hot3Commission = results.FirstOrDefault(r => r.AgentName == "HOT Level 3"); Assert.IsNotNull(hot3Commission); Assert.AreEqual(120m, hot3Commission.NetAmount); } [TestMethod] public void CalculateTotalCommission_ForMultipleResults_ReturnsCorrectTotal() { // Arrange var results = new List<CommissionCalculationResult> { new CommissionCalculationResult { NetAmount = 100m }, new CommissionCalculationResult { NetAmount = 200m }, new CommissionCalculationResult { NetAmount = 300m } }; // Act var total = _service.CalculateTotalCommission(results); // Assert Assert.AreEqual(600m, total); } } } // Program.cs - Console Application Example using CommissionScheme.Models; using CommissionScheme.Services; using System; using System.Collections.Generic; namespace CommissionScheme { class Program { static void Main(string[] args) { var service = new CommissionCalculatorService(); Console.WriteLine("Commission Calculation System"); Console.WriteLine("=============================\n"); // Scenario 1 Example Console.WriteLine("SCENARIO 1 - Original Commission Structure"); Console.WriteLine("------------------------------------------"); var scenario1Hierarchy = CreateScenario1Hierarchy(); var sale1 = new Sale { Id = 1, AgentId = 246499, Amount = 10000, Date = DateTime.Now }; var results1 = service.CalculateCommissions(scenario1Hierarchy, sale1, CommissionScenario.Scenario1); Console.WriteLine("Commission Distribution for $10,000 sale:"); foreach (var result in results1) { Console.WriteLine($"{result.AgentName} ({result.Role}): " + $"Gross: ${result.GrossAmount:F2}, Net: ${result.NetAmount:F2}"); } var total1 = service.CalculateTotalCommission(results1); Console.WriteLine($"Total Commission: ${total1:F2}\n"); // Scenario 2 Example Console.WriteLine("SCENARIO 2 - Extended Commission Structure"); Console.WriteLine("------------------------------------------"); var scenario2Hierarchy = CreateScenario2Hierarchy(); var sale2 = new Sale { Id = 2, AgentId = 246499, Amount = 10000, Date = DateTime.Now }; var results2 = service.CalculateCommissions(scenario2Hierarchy, sale2, CommissionScenario.Scenario2); Console.WriteLine("Commission Distribution for $10,000 sale:"); foreach (var result in results2) { Console.WriteLine($"{result.AgentName} ({result.Role}): " + $"Gross: ${result.GrossAmount:F2}, Net: ${result.NetAmount:F2}"); } var total2 = service.CalculateTotalCommission(results2); Console.WriteLine($"Total Commission: ${total2:F2}\n"); // Comparison Console.WriteLine("COMPARISON"); Console.WriteLine("----------"); Console.WriteLine($"Scenario 1 Total: ${total1:F2}"); Console.WriteLine($"Scenario 2 Total: ${total2:F2}"); Console.WriteLine($"Difference: ${total2 - total1:F2}"); } private static List<Agent> CreateScenario1Hierarchy() { var pic = new Agent { Id = 1, Name = "Company", Role = "PIC", ParentId = null }; var vp = new Agent { Id = 17, Name = "Aaron Siow", Role = "VP", ParentId = 1 }; var hot = new Agent { Id = 11770, Name = "Lee Zi Han", Role = "HOT", ParentId = 17 }; var tl = new Agent { Id = 223681, Name = "Kuhen", Role = "TL", ParentId = 11770 }; var agent1 = new Agent { Id = 227219, Name = "Lankas Ravindran", Role = "Agent", ParentId = 223681 }; var agent2 = new Agent { Id = 246499, Name = "A. Mohan", Role = "Agent", ParentId = 227219 }; pic.Children.Add(vp); vp.Children.Add(hot); hot.Children.Add(tl); tl.Children.Add(agent1); agent1.Children.Add(agent2); return new List<Agent> { pic }; } private static List<Agent> CreateScenario2Hierarchy() { var pic = new Agent { Id = 1, Name = "Company", Role = "PIC", ParentId = null }; var rgr = new Agent { Id = 17, Name = "Regional Head", Role = "RGR", ParentId = 1 }; var vp2 = new Agent { Id = 18, Name = "VP Level 2", Role = "VP2", ParentId = 17 }; var vp1 = new Agent { Id = 19, Name = "VP Level 1", Role = "VP1", ParentId = 18 }; var dos5 = new Agent { Id = 20, Name = "DOS Level 5", Role = "DOS5", ParentId = 19 }; var hot3 = new Agent { Id = 21, Name = "HOT Level 3", Role = "HOT3", ParentId = 20 }; var hot2 = new Agent { Id = 22, Name = "HOT Level 2", Role = "HOT2", ParentId = 21 }; var tl = new Agent { Id = 223681, Name = "Kuhen", Role = "TL", ParentId = 22 }; var agent1 = new Agent { Id = 227219, Name = "Lankas Ravindran", Role = "Agent", ParentId = 223681 }; var agent2 = new Agent { Id = 246499, Name = "A. Mohan", Role = "Agent", ParentId = 227219 }; pic.Children.Add(rgr); rgr.Children.Add(vp2); vp2.Children.Add(vp1); vp1.Children.Add(dos5); dos5.Children.Add(hot3); hot3.Children.Add(hot2); hot2.Children.Add(tl); tl.Children.Add(agent1); agent1.Children.Add(agent2); return new List<Agent> { pic }; } } }
Content is user-generated and unverified.
    Commission Scheme Implementation with BDD Tests | Claude