From 6d593eb7bc3e0b10f3c47fdb76f75585d06164d6 Mon Sep 17 00:00:00 2001 From: Farzaneh Gholian Date: Thu, 5 Dec 2024 19:26:16 +0330 Subject: [PATCH 1/3] Implement payment service --- Payment/Program.cs | 185 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 2 deletions(-) diff --git a/Payment/Program.cs b/Payment/Program.cs index 3751555..7dae525 100644 --- a/Payment/Program.cs +++ b/Payment/Program.cs @@ -1,2 +1,183 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +namespace Payment; + +public class Program +{ + public static void Main() + { + Console.Write("Enter payment type (CreditCard/CryptoCurrency): "); + var input = Console.ReadLine(); + + if (!Enum.TryParse(input, true, out PaymentType paymentType)) + { + paymentType = PaymentType.Unsupported; + } + + Console.Write("Enter payment amount: "); + if (!decimal.TryParse(Console.ReadLine(), out var price)) + { + Console.WriteLine("Invalid price. Please enter a valid number."); + return; + } + + var payment = PaymentService.Create(paymentType, price); + + var response = payment.ProcessPayment(price); + + Console.WriteLine(response.Message); + } +} + +public class PaymentService +{ + public static IPaymentService Create(PaymentType type, decimal price) + { + switch (type) + { + case PaymentType.CreditCard: + { + var factory = new CreditCardFactory(); + return factory.CreateInstance(); + } + case PaymentType.CryptoCurrency: + { + var factory = new CryptoCurrencyFactory(); + return factory.CreateInstance(); + } + default: + return new UnsupportedPayment(); + } + } +} + +public interface IPaymentService +{ + Payment ProcessPayment(decimal price); +} + +public sealed class Payment +{ + public decimal? Price { get; init; } + public string? Message { get; init; } +} + +public enum PaymentType +{ + CreditCard, + CryptoCurrency, + Unsupported +} + + +public class CreditCard : IPaymentService +{ + public Payment ProcessPayment(decimal price) + { + var calc = new CreditCardCalculator(); + var finalAmount = calc.CalculatePayment(price); + + var response = new Payment + { + Message = $"Processed credit card payment of {finalAmount}.", + Price = finalAmount + }; + return response; + } +} + +public class CryptoCurrencyAdapter : IPaymentService +{ + private readonly CryptoCurrency _cryptoCurrency = new(); + + public Payment ProcessPayment(decimal price) + { + var response = new Payment + { + Message = $"Processed crypto currency payment of {price}.", + Price = _cryptoCurrency.PayByCrypto(price) + }; + return response; + } +} + +public interface IPaymentCalculator +{ + decimal CalculatePayment(decimal price); +} + +public class CreditCardCalculator : IPaymentCalculator +{ + public decimal CalculatePayment(decimal price) + { + return price + price * (decimal)0.02; + } +} + +public class UnsupportedPayment : IPaymentService +{ + public Payment ProcessPayment(decimal price) + { + return new Payment + { + Message = "Unsupported Payment" + }; + } +} + + +public interface IPaymentServiceFactory +{ + IPaymentService CreateInstance(); +} + +public class CreditCardFactory : IPaymentServiceFactory +{ + public IPaymentService CreateInstance() + { + return new CreditCard(); + } +} + +public class CryptoCurrencyFactory : IPaymentServiceFactory +{ + public IPaymentService CreateInstance() + { + return new CryptoCurrencyAdapter(); + } +} + +// External library class (inaccessible for modification) +//public class CryptoCurrency +//{ +// public decimal PayByCrypto(decimal price) +// { +// return price; +// } +//} + +public sealed class CryptoCurrency +{ + private const decimal ConversionRate = 0.0005m; + private const decimal TransactionFee = 0.02m; + + public decimal PayByCrypto(decimal price) + { + var cryptoAmount = ConvertToCrypto(price); + var totalAmount = ApplyTransactionFee(cryptoAmount); + + Console.WriteLine($"پرداخت کریپتو به مبلغ {totalAmount} در حال پردازش است."); + + return totalAmount; + } + + private decimal ConvertToCrypto(decimal price) + { + return price * ConversionRate; + } + + private decimal ApplyTransactionFee(decimal cryptoAmount) + { + return cryptoAmount - (cryptoAmount * TransactionFee); + } +} + + From 84ed446bdc8076df5bfc3144b52f2e97584872ed Mon Sep 17 00:00:00 2001 From: Farzaneh Gholian Date: Fri, 6 Dec 2024 14:15:13 +0330 Subject: [PATCH 2/3] Implement points mentions --- Payment/Payment.csproj | 5 ++ Payment/Program.cs | 140 +++++++++++++++++++++++++++++------------ 2 files changed, 104 insertions(+), 41 deletions(-) diff --git a/Payment/Payment.csproj b/Payment/Payment.csproj index 2150e37..e491120 100644 --- a/Payment/Payment.csproj +++ b/Payment/Payment.csproj @@ -7,4 +7,9 @@ enable + + + + + diff --git a/Payment/Program.cs b/Payment/Program.cs index 7dae525..6d56e77 100644 --- a/Payment/Program.cs +++ b/Payment/Program.cs @@ -1,9 +1,15 @@ -namespace Payment; +using Microsoft.Extensions.DependencyInjection; + +namespace Payment; public class Program { public static void Main() { + // DI + var serviceProvider = ConfigureServices(); + var paymentService = serviceProvider.GetRequiredService(); + Console.Write("Enter payment type (CreditCard/CryptoCurrency): "); var input = Console.ReadLine(); @@ -19,39 +25,38 @@ public static void Main() return; } - var payment = PaymentService.Create(paymentType, price); - - var response = payment.ProcessPayment(price); + var payment = paymentService.Create(paymentType); + var response = payment.ProcessPayment(price, input); Console.WriteLine(response.Message); } + + // Config DI + private static ServiceProvider ConfigureServices() + { + return new ServiceCollection() + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient() + .BuildServiceProvider(); + } } -public class PaymentService +public class PaymentService(IEnumerable factories) { - public static IPaymentService Create(PaymentType type, decimal price) + public IPaymentService Create(PaymentType type) { - switch (type) - { - case PaymentType.CreditCard: - { - var factory = new CreditCardFactory(); - return factory.CreateInstance(); - } - case PaymentType.CryptoCurrency: - { - var factory = new CryptoCurrencyFactory(); - return factory.CreateInstance(); - } - default: - return new UnsupportedPayment(); - } + return factories + .FirstOrDefault(f => f.PaymentType == type)?.CreateInstance() + ?? new UnsupportedPayment(); } } public interface IPaymentService { - Payment ProcessPayment(decimal price); + Payment ProcessPayment(decimal price, string type); } public sealed class Payment @@ -70,14 +75,15 @@ public enum PaymentType public class CreditCard : IPaymentService { - public Payment ProcessPayment(decimal price) + private readonly IPaymentCalculator _paymentCalculator = new CreditCardCalculator(); + + public Payment ProcessPayment(decimal price, string type) { - var calc = new CreditCardCalculator(); - var finalAmount = calc.CalculatePayment(price); + var finalAmount = _paymentCalculator.CalculatePayment(price); var response = new Payment { - Message = $"Processed credit card payment of {finalAmount}.", + Message = PaymentMessageGenerator.GeneratePaymentMessage($"{type}", price, finalAmount), Price = finalAmount }; return response; @@ -87,18 +93,26 @@ public Payment ProcessPayment(decimal price) public class CryptoCurrencyAdapter : IPaymentService { private readonly CryptoCurrency _cryptoCurrency = new(); + private readonly CryptoCurrencyCalculator _paymentCalculator = new(); - public Payment ProcessPayment(decimal price) + public Payment ProcessPayment(decimal price, string type) { + var adjustedPrice = _paymentCalculator.CalculatePayment(price); + var finalCryptoAmount = _cryptoCurrency.PayByCrypto(adjustedPrice); + var response = new Payment { - Message = $"Processed crypto currency payment of {price}.", - Price = _cryptoCurrency.PayByCrypto(price) + Message = PaymentMessageGenerator.GeneratePaymentMessage( + $"{type}", + adjustedPrice, + finalCryptoAmount), + Price = finalCryptoAmount }; return response; } } + public interface IPaymentCalculator { decimal CalculatePayment(decimal price); @@ -112,25 +126,63 @@ public decimal CalculatePayment(decimal price) } } +public class CryptoCurrencyCalculator : IPaymentCalculator +{ + private const decimal TaxRate = 0.05m; + private const decimal DiscountRate = 0.1m; + private const decimal TransactionFeeRate = 0.02m; + + public decimal CalculatePayment(decimal price) + { + var discountedPrice = price - (price * DiscountRate); + + var taxedPrice = discountedPrice + (discountedPrice * TaxRate); + var finalPrice = taxedPrice - (taxedPrice * TransactionFeeRate); + + return finalPrice; + } +} + + public class UnsupportedPayment : IPaymentService { - public Payment ProcessPayment(decimal price) + private readonly ILogger _logger = new ConsoleLogger(); + + public Payment ProcessPayment(decimal price,string type) { + _logger.Log($"Unsupported payment type {type}. Price: {price}. Timestamp: {DateTime.UtcNow}"); + return new Payment { - Message = "Unsupported Payment" + Message = $"Unsupported {type} payment. Unable to process {price} at this time." }; } } +public interface ILogger +{ + void Log(string message); +} + +public class ConsoleLogger : ILogger +{ + public void Log(string message) + { + Console.WriteLine($"[LOG]: {message}"); + } +} + public interface IPaymentServiceFactory { + PaymentType PaymentType { get; } IPaymentService CreateInstance(); } public class CreditCardFactory : IPaymentServiceFactory { + public PaymentType PaymentType => PaymentType.CreditCard; + public IPaymentService CreateInstance() { return new CreditCard(); @@ -139,32 +191,38 @@ public IPaymentService CreateInstance() public class CryptoCurrencyFactory : IPaymentServiceFactory { + public PaymentType PaymentType => PaymentType.CryptoCurrency; + public IPaymentService CreateInstance() { return new CryptoCurrencyAdapter(); } } +public static class PaymentMessageGenerator +{ + public static string GeneratePaymentMessage(string paymentType, decimal originalPrice, decimal adjustedPrice) + { + return adjustedPrice == originalPrice + ? $"Payment via {paymentType}: Amount {originalPrice}." + : $"Payment via {paymentType}: Original amount {originalPrice}, Final amount after adjustment {adjustedPrice}."; + } +} + + // External library class (inaccessible for modification) -//public class CryptoCurrency -//{ -// public decimal PayByCrypto(decimal price) -// { -// return price; -// } -//} public sealed class CryptoCurrency { - private const decimal ConversionRate = 0.0005m; - private const decimal TransactionFee = 0.02m; + private const decimal ConversionRate = 0.0005m; + private const decimal TransactionFee = 0.02m; public decimal PayByCrypto(decimal price) { var cryptoAmount = ConvertToCrypto(price); var totalAmount = ApplyTransactionFee(cryptoAmount); - Console.WriteLine($"پرداخت کریپتو به مبلغ {totalAmount} در حال پردازش است."); + Console.WriteLine($"Processing cryptocurrency payment of {totalAmount} units."); return totalAmount; } From 816e436568f8d82fa564c59482677bb35e023d22 Mon Sep 17 00:00:00 2001 From: Farzaneh Gholian Date: Wed, 11 Dec 2024 18:32:25 +0330 Subject: [PATCH 3/3] bug reporter --- Examples/Examples.sln | 9 ++ Examples/Reporting/Program.cs | 166 ++++++++++++++++++++++++++++ Examples/Reporting/Reporting.csproj | 15 +++ 3 files changed, 190 insertions(+) create mode 100644 Examples/Reporting/Program.cs create mode 100644 Examples/Reporting/Reporting.csproj diff --git a/Examples/Examples.sln b/Examples/Examples.sln index 0fd3d0a..1e9ca21 100644 --- a/Examples/Examples.sln +++ b/Examples/Examples.sln @@ -11,6 +11,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RealExample", "RealExample" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Payment", "..\Payment\Payment.csproj", "{E7F0B3A7-6105-43CB-B4E1-3733111D4EB8}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReportingSystem", "ReportingSystem", "{7F5E5CAF-808E-4B01-9020-FFFB3E91E830}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reporting", "Reporting\Reporting.csproj", "{E3DE53A2-4252-4A90-91B8-2F4881F0169A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,12 +33,17 @@ Global {E7F0B3A7-6105-43CB-B4E1-3733111D4EB8}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7F0B3A7-6105-43CB-B4E1-3733111D4EB8}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7F0B3A7-6105-43CB-B4E1-3733111D4EB8}.Release|Any CPU.Build.0 = Release|Any CPU + {E3DE53A2-4252-4A90-91B8-2F4881F0169A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3DE53A2-4252-4A90-91B8-2F4881F0169A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3DE53A2-4252-4A90-91B8-2F4881F0169A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3DE53A2-4252-4A90-91B8-2F4881F0169A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {E7F0B3A7-6105-43CB-B4E1-3733111D4EB8} = {BEFC8EDE-A568-4AC3-B3EA-B68427103370} + {E3DE53A2-4252-4A90-91B8-2F4881F0169A} = {7F5E5CAF-808E-4B01-9020-FFFB3E91E830} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {22B9C537-2B7B-4D6D-B152-E2C4BA31F193} diff --git a/Examples/Reporting/Program.cs b/Examples/Reporting/Program.cs new file mode 100644 index 0000000..8307ac5 --- /dev/null +++ b/Examples/Reporting/Program.cs @@ -0,0 +1,166 @@ +using Microsoft.Extensions.DependencyInjection; +using System.ComponentModel; +using System.Reflection; + +public class Program +{ + public static void Main() + { + // DI + var serviceProvider = ConfigureServices(); + var connectors = serviceProvider.GetRequiredService(); + + Console.Write("Enter Title: "); + var title = Console.ReadLine(); + + Console.Write("Enter Description: "); + var description = Console.ReadLine(); + + Console.Write("Enter Severity(Dangerous, Medium, LowImportance): "); + var severityInput = Console.ReadLine(); + var severity = Enum.TryParse(severityInput, out Severity parsedSeverity) ? parsedSeverity : Severity.LowImportance; + + var report = new BugReport + { + Title = title, + Description = description, + Severity = severity + }; + + report.Validate(); + + Console.Write("Enter Connector (Discord, Jira, Slack): "); + var connectorType = Console.ReadLine(); + + connectors.Create(connectorType); + } + + // Config DI + private static ServiceProvider ConfigureServices() + { + return new ServiceCollection() + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient() + .BuildServiceProvider(); + } +} + +public class Connectors +{ + private readonly IEnumerable _factories; + + public Connectors(IEnumerable factories) + { + _factories = factories; + } + + public IConnectors Create(string connectorType) + { + var factory = _factories.FirstOrDefault(f => f.GetType().Name.ToLower().Contains(connectorType)); + return factory?.CreateInstance(); + } +} + +public class BugReport +{ + public string Title { get; init; } = default!; + public string Description { get; init; } = default!; + public Severity Severity { get; init; } + public DateTime CreationDate { get;} = DateTime.UtcNow; + + public void Validate() + { + if (string.IsNullOrWhiteSpace(Title)) + throw new ArgumentException("Title cannot be null, empty, or whitespace.", nameof(Title)); + + if (string.IsNullOrWhiteSpace(Description)) + throw new ArgumentException("Description cannot be null, empty, or whitespace.", nameof(Description)); + } + + public string Format() + { + var severityLabel = Severity.GetDescription(); + return $"[{severityLabel}] {Title}: {Description} (Created On: {CreationDate:yyyy-MM-dd HH:mm:ss})"; + } +} + +public enum Severity +{ + [Description("High")] + Dangerous = 0, + [Description("Medium")] + Medium = 1, + [Description("Low")] + LowImportance = 2 +} + +public static class EnumExtensions +{ + public static string GetDescription(this Enum value) + { + var field = value.GetType().GetField(value.ToString()); + var attribute = field!.GetCustomAttribute(); + return attribute == null ? value.ToString() : attribute.Description; + } +} + +public interface IConnectors +{ + void SendBugReport(BugReport report); +} + +public class Jira : IConnectors +{ + public void SendBugReport(BugReport report) + { + Console.WriteLine($"[Jira] Bug Report Sent: {report.Format()}"); + } +} + +public class Slack : IConnectors +{ + public void SendBugReport(BugReport report) + { + Console.WriteLine($"[Slack] Bug Report Sent: {report.Format()}"); + } +} + +public class Discord : IConnectors +{ + public void SendBugReport(BugReport report) + { + Console.WriteLine($"[Discord] Bug Report Sent: {report.Format()}"); + } +} + +public interface IConnectorsFactory +{ + IConnectors CreateInstance(); +} + +public class JiraFactory : IConnectorsFactory +{ + public IConnectors CreateInstance() + { + return new Jira(); + } +} + +public class SlackFactory : IConnectorsFactory +{ + public IConnectors CreateInstance() + { + return new Slack(); + } +} + +public class DiscordFactory : IConnectorsFactory +{ + public IConnectors CreateInstance() + { + return new Discord(); + } +} + diff --git a/Examples/Reporting/Reporting.csproj b/Examples/Reporting/Reporting.csproj new file mode 100644 index 0000000..6b07759 --- /dev/null +++ b/Examples/Reporting/Reporting.csproj @@ -0,0 +1,15 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + +