|
1 | 1 | using System;
|
| 2 | +using System.Collections; |
| 3 | +using System.Collections.Generic; |
| 4 | +using System.Diagnostics.Contracts; |
| 5 | +using System.Linq; |
2 | 6 |
|
3 | 7 | namespace DesignPatternsInCSharp.RulesEngine.Discounts
|
4 | 8 | {
|
5 |
| - public class DiscountCalculator |
| 9 | + // View History |
| 10 | + // https://github.githistory.xyz/ardalis/DesignPatternsInCSharp/blob/master/DesignPatternsInCSharp/RulesEngine/Discounts/DiscountCalculator.cs |
| 11 | + public interface IDiscountRule |
6 | 12 | {
|
7 |
| - public decimal CalculateDiscountPercentage(Customer customer) |
| 13 | + decimal CalculateDiscount(Customer customer, decimal currentDiscount); |
| 14 | + } |
| 15 | + |
| 16 | + public class FirstTimeCustomerRule : IDiscountRule |
| 17 | + { |
| 18 | + public decimal CalculateDiscount(Customer customer, decimal currentDiscount) |
8 | 19 | {
|
9 |
| - bool isBirthday = customer.DateOfBirth.HasValue && customer.DateOfBirth.Value.Month == DateTime.Today.Month && customer.DateOfBirth.Value.Day == DateTime.Today.Day; |
10 | 20 | if (!customer.DateOfFirstPurchase.HasValue)
|
11 | 21 | {
|
12 | 22 | return .15m;
|
13 | 23 | }
|
14 |
| - else |
| 24 | + return 0; |
| 25 | + } |
| 26 | + } |
| 27 | + |
| 28 | + public class LoyalCustomerRule : IDiscountRule |
| 29 | + { |
| 30 | + public decimal CalculateDiscount(Customer customer, decimal currentDiscount) |
| 31 | + { |
| 32 | + if (customer.DateOfFirstPurchase.HasValue) |
15 | 33 | {
|
16 | 34 | if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-15))
|
17 | 35 | {
|
18 |
| - if (isBirthday) return .25m; |
19 | 36 | return .15m;
|
20 | 37 | }
|
21 | 38 | if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-10))
|
22 | 39 | {
|
23 |
| - if (isBirthday) return .22m; |
24 | 40 | return .12m;
|
25 | 41 | }
|
26 | 42 | if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-5))
|
27 | 43 | {
|
28 |
| - if (isBirthday) return .20m; |
29 | 44 | return .10m;
|
30 | 45 | }
|
31 |
| - if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-2) && |
32 |
| - !customer.IsVeteran) |
| 46 | + if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-2)) |
33 | 47 | {
|
34 |
| - if (isBirthday) return .18m; |
35 | 48 | return .08m;
|
36 | 49 | }
|
37 |
| - if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-1) && |
38 |
| - !customer.IsVeteran) |
| 50 | + if (customer.DateOfFirstPurchase.Value < DateTime.Now.AddYears(-1)) |
39 | 51 | {
|
40 |
| - if (isBirthday) return .15m; |
41 | 52 | return .05m;
|
42 | 53 | }
|
43 | 54 | }
|
| 55 | + return 0; |
| 56 | + } |
| 57 | + } |
44 | 58 |
|
| 59 | + public class VeteranRule : IDiscountRule |
| 60 | + { |
| 61 | + public decimal CalculateDiscount(Customer customer, decimal currentDiscount) |
| 62 | + { |
45 | 63 | if (customer.IsVeteran)
|
46 | 64 | {
|
47 |
| - if (isBirthday) return .20m; |
48 | 65 | return .10m;
|
49 | 66 | }
|
50 |
| - |
51 |
| - if(customer.DateOfBirth < DateTime.Now.AddYears(-65)) |
| 67 | + return 0; |
| 68 | + } |
| 69 | + } |
| 70 | + public class SeniorRule : IDiscountRule |
| 71 | + { |
| 72 | + public decimal CalculateDiscount(Customer customer, decimal currentDiscount) |
| 73 | + { |
| 74 | + if (customer.DateOfBirth < DateTime.Now.AddYears(-65)) |
52 | 75 | {
|
53 |
| - if (isBirthday) return .15m; |
54 | 76 | return .05m;
|
55 | 77 | }
|
| 78 | + return 0; |
| 79 | + } |
| 80 | + } |
56 | 81 |
|
57 |
| - if (isBirthday) return .10m; |
| 82 | + public class BirthdayRule : IDiscountRule |
| 83 | + { |
| 84 | + public decimal CalculateDiscount(Customer customer, decimal currentDiscount) |
| 85 | + { |
| 86 | + bool isBirthday = customer.DateOfBirth.HasValue && customer.DateOfBirth.Value.Month == DateTime.Today.Month && customer.DateOfBirth.Value.Day == DateTime.Today.Day; |
58 | 87 |
|
59 |
| - return 0; |
| 88 | + if (isBirthday) return currentDiscount + 0.10m; |
| 89 | + return currentDiscount; |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + public class DiscountRuleEngine |
| 94 | + { |
| 95 | + List<IDiscountRule> _rules = new List<IDiscountRule>(); |
| 96 | + |
| 97 | + public DiscountRuleEngine(IEnumerable<IDiscountRule> rules) |
| 98 | + { |
| 99 | + _rules.AddRange(rules); |
| 100 | + } |
| 101 | + |
| 102 | + public decimal CalculateDiscountPercentage(Customer customer) |
| 103 | + { |
| 104 | + decimal discount = 0m; |
| 105 | + foreach(var rule in _rules) |
| 106 | + { |
| 107 | + discount = Math.Max(discount, rule.CalculateDiscount(customer, discount)); |
| 108 | + } |
| 109 | + return discount; |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + public class DiscountCalculator |
| 114 | + { |
| 115 | + public decimal CalculateDiscountPercentage(Customer customer) |
| 116 | + { |
| 117 | + var ruleType = typeof(IDiscountRule); |
| 118 | + IEnumerable<IDiscountRule> rules = this.GetType().Assembly.GetTypes() |
| 119 | + .Where(p => ruleType.IsAssignableFrom(p) && !p.IsInterface) |
| 120 | + .Select(r => Activator.CreateInstance(r) as IDiscountRule); |
| 121 | + |
| 122 | + var engine = new DiscountRuleEngine(rules); |
| 123 | + |
| 124 | + return engine.CalculateDiscountPercentage(customer); |
60 | 125 | }
|
61 | 126 | }
|
62 | 127 | }
|
0 commit comments