├── assets ├── sonar_runtime_01.png ├── sonar_runtime_02.png ├── sonar_runtime_03.png ├── sonar_runtime_04.png ├── sonar_runtime_05.png ├── sonar_runtime_06.png ├── sonar_runtime_07.png ├── sonar_runtime_08.png ├── sonar_runtime_09.png ├── sonar_runtime_10.png ├── sonar_runtime_11.png ├── sonar_runtime_12.png ├── sonar_runtime_13.png ├── sonar_runtime_14.png ├── sonar_runtime_15.png ├── sonar_runtime_16.png └── sonar_runtime_17.png ├── ModelLib ├── IntegratorStatus.cs ├── Category.cs ├── Company.cs ├── ModelLib.csproj ├── Order.cs ├── ShipmentCompany.cs ├── Waybill.cs ├── Customer.cs └── Product.cs ├── CommonLib ├── Exceptions │ ├── IntegratorException.cs │ ├── ReportException.cs │ └── ShippingException.cs ├── CommonLib.csproj └── FileLogger.cs ├── BusinessLib ├── BusinessLib.csproj └── Ordering.cs ├── ClientApp ├── ClientApp.csproj └── Program.cs ├── RepositoryLib ├── RepositoryLib.csproj ├── GovermentIntegrator.cs ├── NorthwindDbContext.cs └── DbUtilities.cs ├── docker-compose.yml ├── sonar-kule.sln ├── README.md └── .gitignore /assets/sonar_runtime_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_01.png -------------------------------------------------------------------------------- /assets/sonar_runtime_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_02.png -------------------------------------------------------------------------------- /assets/sonar_runtime_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_03.png -------------------------------------------------------------------------------- /assets/sonar_runtime_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_04.png -------------------------------------------------------------------------------- /assets/sonar_runtime_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_05.png -------------------------------------------------------------------------------- /assets/sonar_runtime_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_06.png -------------------------------------------------------------------------------- /assets/sonar_runtime_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_07.png -------------------------------------------------------------------------------- /assets/sonar_runtime_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_08.png -------------------------------------------------------------------------------- /assets/sonar_runtime_09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_09.png -------------------------------------------------------------------------------- /assets/sonar_runtime_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_10.png -------------------------------------------------------------------------------- /assets/sonar_runtime_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_11.png -------------------------------------------------------------------------------- /assets/sonar_runtime_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_12.png -------------------------------------------------------------------------------- /assets/sonar_runtime_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_13.png -------------------------------------------------------------------------------- /assets/sonar_runtime_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_14.png -------------------------------------------------------------------------------- /assets/sonar_runtime_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_15.png -------------------------------------------------------------------------------- /assets/sonar_runtime_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_16.png -------------------------------------------------------------------------------- /assets/sonar_runtime_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/sonar-kule/HEAD/assets/sonar_runtime_17.png -------------------------------------------------------------------------------- /ModelLib/IntegratorStatus.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public enum IntegratorStatus{ 4 | Success, 5 | WaybillInvalid, 6 | LimitError, 7 | FraudDetected 8 | } -------------------------------------------------------------------------------- /ModelLib/Category.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class Category 4 | { 5 | public int CategoryId { get; set; } 6 | public string Title { get; set; } 7 | public string Description { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /ModelLib/Company.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class Company 4 | { 5 | public int CompanyId { get; set; } 6 | public string Name { get; set; } 7 | public Country Country { get; set; } 8 | public int Level { get; set; } 9 | } -------------------------------------------------------------------------------- /CommonLib/Exceptions/IntegratorException.cs: -------------------------------------------------------------------------------- 1 | namespace CommonLib.Exceptions; 2 | 3 | public class IntegratorException 4 | : Exception 5 | { 6 | public IntegratorException(String message) 7 | : base(message) 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CommonLib/Exceptions/ReportException.cs: -------------------------------------------------------------------------------- 1 | namespace CommonLib.Exceptions; 2 | 3 | public class ReportException 4 | : Exception 5 | { 6 | public ReportException() 7 | : base("Raporlamada bir sorun oluştu.") 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CommonLib/CommonLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ModelLib/ModelLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /CommonLib/Exceptions/ShippingException.cs: -------------------------------------------------------------------------------- 1 | namespace CommonLib.Exceptions; 2 | 3 | public class ShippingException 4 | : Exception 5 | { 6 | public ShippingException() 7 | : base("Sipariş işleminde oluşan genel hata. Lütfen sistem yöneticisine başvurun veya ticket açın.") 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ModelLib/Order.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class Order 4 | { 5 | public int OrderId { get; set; } 6 | public DateTime OrderDate { get; set; } 7 | public int Quantity { get; set; } 8 | public ShipmentCompany ShipmentCompany { get; set; } 9 | public Customer Customer { get; set; } 10 | public string DestinationAddress { get; set; } 11 | public PaymentType PaymentType { get; set; } 12 | } -------------------------------------------------------------------------------- /ModelLib/ShipmentCompany.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class ShipmentCompany 4 | { 5 | public int CompanyId { get; set; } 6 | public string Name { get; set; } 7 | public Country Country { get; set; } 8 | public int Level { get; set; } 9 | public List ServedCities { get; set; } = new List(); 10 | } 11 | 12 | public class City{ 13 | public int Id { get; set; } 14 | public string Name { get; set; } 15 | } -------------------------------------------------------------------------------- /ModelLib/Waybill.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class Waybill 4 | { 5 | public string Address { get; set; } 6 | public string CustomerFullName { get; set; } 7 | public DateTime Date { get; set; } 8 | public object PaymentType { get; set; } 9 | public int OrderId { get; set; } 10 | } 11 | 12 | public enum PaymentType 13 | { 14 | CreditCard, 15 | DebitCard, 16 | DigitalCoin, 17 | Cash, 18 | Gold 19 | } -------------------------------------------------------------------------------- /ModelLib/Customer.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class Customer{ 4 | public int CustomerId { get; set; } 5 | public string Name { get; set; } 6 | public string MiddleName { get; set; } 7 | public string LastName { get; set; } 8 | public MemberType MemberType { get; set; } 9 | public string City { get; set; } 10 | public bool IsSuspicious { get; set; } 11 | } 12 | 13 | public enum MemberType{ 14 | Gold, 15 | Platinium, 16 | Regular 17 | } -------------------------------------------------------------------------------- /BusinessLib/BusinessLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | net7.0 11 | enable 12 | enable 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ClientApp/ClientApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Exe 11 | net7.0 12 | enable 13 | enable 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /RepositoryLib/RepositoryLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | net7.0 15 | enable 16 | enable 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ModelLib/Product.cs: -------------------------------------------------------------------------------- 1 | namespace ModelLib; 2 | 3 | public class Product 4 | { 5 | public int ProductId { get; set; } 6 | public string Name { get; set; } 7 | public decimal ListPrice { get; set; } 8 | public int StockLevel { get; set; } 9 | public int CategoryId { get; set; } 10 | public bool OnSales { get; set; } 11 | public float DiscountRate { get; set; } 12 | public Country Country { get; set; } 13 | public Company Company { get; set; } 14 | public Order[] Orders { get; set; } 15 | public DateTime CreateDate { get; set; } 16 | } 17 | 18 | public enum Country 19 | { 20 | USA, 21 | Japan, 22 | Australia, 23 | England, 24 | Turkey 25 | } -------------------------------------------------------------------------------- /ClientApp/Program.cs: -------------------------------------------------------------------------------- 1 | using ModelLib; 2 | using RepositoryLib; 3 | 4 | var crudUtility = new CRUDUtility(); 5 | var result = crudUtility.CreateCategoryWithProducts( 6 | "Books" 7 | , "Kitaplar ile ilgili kategori" 8 | , "Clean Code :P" 9 | , 190.30M 10 | , 100 11 | , true 12 | , DateTime.Now.AddYears(-20) 13 | , 0.0F 14 | , Country.USA 15 | , new ModelLib.Company 16 | { 17 | Country = Country.England, 18 | Level = 100, 19 | Name = "GG Book Deployer", 20 | CompanyId = 12 21 | 22 | }); 23 | 24 | Console.WriteLine("Kategori ve ürün eklendi"); 25 | 26 | // var result2 = crudUtility.AddOrdersToProductAndStartShipments(1, new Order[1]{ 27 | // null 28 | // }); 29 | -------------------------------------------------------------------------------- /RepositoryLib/GovermentIntegrator.cs: -------------------------------------------------------------------------------- 1 | using ModelLib; 2 | 3 | namespace RepositoryLib 4 | { 5 | public class GovermentIntegrator 6 | { 7 | public GovermentIntegrator(string notificationAddress) 8 | { 9 | NotificationAddress = notificationAddress; 10 | } 11 | 12 | public string NotificationAddress { get; } 13 | 14 | public bool Connect(string apiKey, string apiPass) 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public IntegratorResponse PostWaybill(Waybill waybill) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | 25 | public class IntegratorResponse{ 26 | public string Message { get; set; } 27 | public IntegratorStatus Status { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | sonarqube: 5 | image: sonarqube:lts-community 6 | depends_on: 7 | - db 8 | environment: 9 | SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar 10 | SONAR_JDBC_USERNAME: sonar 11 | SONAR_JDBC_PASSWORD: sonar 12 | volumes: 13 | - sonarqube_data:/opt/sonarqube/data 14 | - sonarqube_extensions:/opt/sonarqube/extensions 15 | - sonarqube_logs:/opt/sonarqube/logs 16 | ports: 17 | - "9000:9000" 18 | db: 19 | image: postgres:12 20 | environment: 21 | POSTGRES_USER: sonar 22 | POSTGRES_PASSWORD: sonar 23 | volumes: 24 | - postgresql:/var/lib/postgresql 25 | - postgresql_data:/var/lib/postgresql/data 26 | 27 | volumes: 28 | sonarqube_data: 29 | sonarqube_extensions: 30 | sonarqube_logs: 31 | postgresql: 32 | postgresql_data: -------------------------------------------------------------------------------- /CommonLib/FileLogger.cs: -------------------------------------------------------------------------------- 1 | namespace CommonLib; 2 | 3 | public class FileLogger 4 | { 5 | private string fileName = Path.Combine(Environment.CurrentDirectory, "application.logs"); 6 | public async void InfoAsync(String content, String source) 7 | { 8 | String logMessage = "INFO: Source" + source + ", " + DateTime.Now.ToLongTimeString() + ":" + content; 9 | System.IO.File.AppendAllText(fileName, logMessage); 10 | } 11 | public async void WarnAsync(String content, String source) 12 | { 13 | String logMessage = "WARN: Source" + source + ", " + DateTime.Now.ToLongTimeString() + ":" + content; 14 | System.IO.File.AppendAllText(fileName, logMessage); 15 | } 16 | 17 | public async void ErrorAsync(String source, String exceptionMessage) 18 | { 19 | String logMessage = "ERROR: Source" + source + ", " + DateTime.Now.ToLongTimeString() + ":" + exceptionMessage; 20 | System.IO.File.AppendAllText(fileName, logMessage); 21 | } 22 | } -------------------------------------------------------------------------------- /sonar-kule.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31903.59 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelLib", "ModelLib\ModelLib.csproj", "{4F25761C-3956-4C89-B20F-7E75C7701C4F}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RepositoryLib", "RepositoryLib\RepositoryLib.csproj", "{CA693EDE-F578-433C-8F51-B8EA8124AF1A}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonLib", "CommonLib\CommonLib.csproj", "{492DAACA-0ADC-4396-906C-7E328BF6FE4B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientApp", "ClientApp\ClientApp.csproj", "{6228D8A0-554C-4AB6-BC05-9AB69BF69D05}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLib", "BusinessLib\BusinessLib.csproj", "{A1E49C8B-11F1-4083-AF2A-032843EAA480}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {4F25761C-3956-4C89-B20F-7E75C7701C4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {4F25761C-3956-4C89-B20F-7E75C7701C4F}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {4F25761C-3956-4C89-B20F-7E75C7701C4F}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {4F25761C-3956-4C89-B20F-7E75C7701C4F}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {CA693EDE-F578-433C-8F51-B8EA8124AF1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {CA693EDE-F578-433C-8F51-B8EA8124AF1A}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {CA693EDE-F578-433C-8F51-B8EA8124AF1A}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {CA693EDE-F578-433C-8F51-B8EA8124AF1A}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {492DAACA-0ADC-4396-906C-7E328BF6FE4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {492DAACA-0ADC-4396-906C-7E328BF6FE4B}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {492DAACA-0ADC-4396-906C-7E328BF6FE4B}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {492DAACA-0ADC-4396-906C-7E328BF6FE4B}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {6228D8A0-554C-4AB6-BC05-9AB69BF69D05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {6228D8A0-554C-4AB6-BC05-9AB69BF69D05}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {6228D8A0-554C-4AB6-BC05-9AB69BF69D05}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {6228D8A0-554C-4AB6-BC05-9AB69BF69D05}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {A1E49C8B-11F1-4083-AF2A-032843EAA480}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {A1E49C8B-11F1-4083-AF2A-032843EAA480}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {A1E49C8B-11F1-4083-AF2A-032843EAA480}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {A1E49C8B-11F1-4083-AF2A-032843EAA480}.Release|Any CPU.Build.0 = Release|Any CPU 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /RepositoryLib/NorthwindDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using ModelLib; 3 | 4 | namespace RepositoryLib 5 | { 6 | public partial class NorthwindDbContext : DbContext 7 | { 8 | public DbSet Categories { get; set; } 9 | public DbSet Companies { get; set; } 10 | public DbSet Customers { get; set; } 11 | public DbSet Orders { get; set; } 12 | public DbSet Products { get; set; } 13 | public DbSet ShipmentCompanies { get; set; } 14 | 15 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 16 | { 17 | optionsBuilder.UseSqlServer("server=localhost;database=companyDb;user=sa;password=1234!"); 18 | } 19 | 20 | public void CreateCategory(Category category) 21 | { 22 | Categories.Add(category); 23 | SaveChanges(); 24 | } 25 | 26 | public void CreateCompany(Company company) 27 | { 28 | Companies.Add(company); 29 | SaveChanges(); 30 | } 31 | 32 | public void CreateCustomer(Customer customer) 33 | { 34 | Customers.Add(customer); 35 | SaveChanges(); 36 | } 37 | 38 | public void CreateOrder(Order order) 39 | { 40 | Orders.Add(order); 41 | SaveChanges(); 42 | } 43 | 44 | public void CreateProduct(Product product) 45 | { 46 | Products.Add(product); 47 | SaveChanges(); 48 | } 49 | 50 | public void CreateShipmentCompany(ShipmentCompany shipmentCompany) 51 | { 52 | ShipmentCompanies.Add(shipmentCompany); 53 | SaveChanges(); 54 | } 55 | 56 | public void DeleteCategory(Category category) 57 | { 58 | Categories.Remove(category); 59 | SaveChanges(); 60 | } 61 | 62 | public void DeleteCompany(Company company) 63 | { 64 | Companies.Remove(company); 65 | SaveChanges(); 66 | } 67 | 68 | public void DeleteCustomer(Customer customer) 69 | { 70 | Customers.Remove(customer); 71 | SaveChanges(); 72 | } 73 | 74 | public void DeleteOrder(Order order) 75 | { 76 | Orders.Remove(order); 77 | SaveChanges(); 78 | } 79 | 80 | public void DeleteProduct(Product product) 81 | { 82 | Products.Remove(product); 83 | SaveChanges(); 84 | } 85 | 86 | public void DeleteShipmentCompany(ShipmentCompany shipmentCompany) 87 | { 88 | ShipmentCompanies.Remove(shipmentCompany); 89 | SaveChanges(); 90 | } 91 | 92 | public Category GetCategory(int categoryId) 93 | { 94 | return Categories.SingleOrDefault(c=>c.CategoryId==categoryId); 95 | } 96 | 97 | public Company GetCompany(int companyId) 98 | { 99 | return Companies.SingleOrDefault(c=>c.CompanyId==companyId); 100 | } 101 | 102 | public Customer GetCustomer(int customerId) 103 | { 104 | return Customers.SingleOrDefault(c=>c.CustomerId==customerId); 105 | } 106 | 107 | public Order GetOrder(int orderId) 108 | { 109 | return Orders.SingleOrDefault(c=>c.OrderId==orderId); 110 | } 111 | 112 | public Product GetProduct(int productId) 113 | { 114 | return Products.SingleOrDefault(c=>c.ProductId==productId); 115 | } 116 | 117 | public ShipmentCompany GetShipmentCompany(int shipmentCompanyId) 118 | { 119 | return ShipmentCompanies.SingleOrDefault(c=>c.CompanyId==shipmentCompanyId); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /RepositoryLib/DbUtilities.cs: -------------------------------------------------------------------------------- 1 | using CommonLib; 2 | using CommonLib.Exceptions; 3 | using ModelLib; 4 | 5 | namespace RepositoryLib; 6 | 7 | public class DBAdapter //BSŞ 06.04.2011 8 | { 9 | public DBAdapter(string connString) 10 | { 11 | //TODO Will create adapter 12 | } 13 | } 14 | public class ConnectionManager //BSŞ 06.04.2011 15 | { 16 | private string _connectionString { get; } = "server=localhost;username=sa;password=1234!;"; 17 | public DBAdapter CreateAdapter(string conStr) 18 | { 19 | var adapter = new DBAdapter(conStr); 20 | return adapter; 21 | //TODO: Must Used Poolling 22 | } 23 | } 24 | 25 | public partial class CRUDUtility 26 | { 27 | private FileLogger _logger; 28 | public CRUDUtility() 29 | { 30 | _logger = new FileLogger(); 31 | } 32 | public bool CreateCategoryWithProducts(string categoryName, string categoryDescription, string productName, decimal listPrice, int stockLevel, bool onSales, DateTime createDate, float discountRate, Country country, Company company) 33 | { 34 | bool result; 35 | try 36 | { 37 | var connMngr = new ConnectionManager(); 38 | var adapter = connMngr.CreateAdapter("server=localhost;database=Northwind;user_id=sa;pwd:1234;integrated security=true"); 39 | //TODO: Insert codes will add 40 | return true; 41 | } 42 | catch (Exception excp) 43 | { 44 | return false; 45 | } 46 | } 47 | 48 | public bool AddOrdersToProductAndStartShipments(int productId, Order[] orders) 49 | { 50 | bool result = false; 51 | Product product = null; 52 | try 53 | { 54 | product = GetProductById(productId); 55 | if (product.CategoryId == 3) 56 | { 57 | if (!product.OnSales || product.StockLevel < 10) 58 | { 59 | return false; 60 | } 61 | } 62 | 63 | var calcResult = CalculateDiscountRate(product); 64 | if (!calcResult) 65 | { 66 | return false; 67 | } 68 | 69 | product.Orders = new Order[orders.Length]; 70 | var index = 0; 71 | foreach (var order in orders) 72 | { 73 | switch (order.Customer.MemberType) 74 | { 75 | case MemberType.Regular: 76 | break; 77 | case MemberType.Gold: 78 | product.DiscountRate += 0.1F; 79 | break; 80 | case MemberType.Platinium: 81 | product.DiscountRate += 0.1F; 82 | break; 83 | } 84 | product.Orders[index] = order; 85 | 86 | switch (order.Customer.City) 87 | { 88 | case "Istanbul": 89 | order.ShipmentCompany = GetShipmentCompanyFromCity(order.Customer.City); 90 | break; 91 | case "Tokyo": 92 | order.ShipmentCompany = GetShipmentCompanyFromCity(order.Customer.City); 93 | break; 94 | case "New York": 95 | order.ShipmentCompany = new ShipmentCompany 96 | { 97 | CompanyId = 1, 98 | Country = Country.USA, 99 | Level = 950, 100 | Name = "YupPiiEss" 101 | }; 102 | break; 103 | case "Berlin": 104 | order.ShipmentCompany = new ShipmentCompany 105 | { 106 | CompanyId = 1, 107 | Country = Country.Australia, 108 | Level = 1000, 109 | Name = "Doyçe Postal" 110 | }; 111 | break; 112 | default: 113 | break; 114 | } 115 | 116 | if (order.PaymentType == PaymentType.DigitalCoin) 117 | { 118 | if (!CheckCustomerStatus(order.Customer, order.PaymentType, product)) 119 | { 120 | return false; 121 | } 122 | } 123 | Waybill waybill = new Waybill 124 | { 125 | Address = order.DestinationAddress, 126 | CustomerFullName = order.Customer.Name + " " + order.Customer.MiddleName + " " + order.Customer.LastName, 127 | Date = DateTime.Now, 128 | PaymentType = order.PaymentType, 129 | OrderId = order.OrderId 130 | }; 131 | 132 | var notificationAddress = "https://nowhere.com/api/governecy/waybill_management"; 133 | var apiKey = "123456789987654321"; 134 | var apiPass = "P@ssw0rd"; 135 | GovermentIntegrator integrator = new GovermentIntegrator(notificationAddress); 136 | var isConnected = integrator.Connect(apiKey, apiPass); 137 | if (isConnected) 138 | { 139 | IntegratorResponse sendResponse = integrator.PostWaybill(waybill); 140 | if (sendResponse.Status != IntegratorStatus.Success) 141 | { 142 | _logger.WarnAsync("Unsuccess the integrator calll", "AddOrdersToProductAndStartShipments Function"); 143 | return false; 144 | } 145 | else 146 | { 147 | if (sendResponse.Status == IntegratorStatus.FraudDetected) 148 | { 149 | _logger.WarnAsync("Fraud detected", "AddOrdersToProductAndStartShipments Function"); 150 | order.Customer.IsSuspicious = true; 151 | } 152 | } 153 | } 154 | else 155 | { 156 | //TODO Must logged this status 157 | throw new IntegratorException("Could not connect to Integrator"); 158 | return false; 159 | } 160 | 161 | index++; 162 | } 163 | } 164 | catch (Exception excp) 165 | { 166 | return false; 167 | } 168 | 169 | return true; 170 | } 171 | 172 | private bool CheckCustomerStatus(Customer customer, PaymentType paymentType, Product product) 173 | { 174 | //TODO: Check the status of customer for payment type 175 | throw new NotImplementedException(); 176 | } 177 | 178 | private ShipmentCompany GetShipmentCompanyFromCity(string city) 179 | { 180 | //TODO: Getting from Redis by City Key 181 | throw new NotImplementedException(); 182 | } 183 | 184 | private Product GetProductById(int productId) 185 | { 186 | return new Product 187 | { 188 | Name = "ElCi Monitor 49 Inch Ultra Super Mega Hydron HD", 189 | CategoryId = 3, 190 | ListPrice = 4599.99M, 191 | StockLevel = 90, 192 | Country = Country.Japan, 193 | Company = new Company 194 | { 195 | Name = "Takaşi Kovaç Associated Press And Mefrüşat Klima San", 196 | Country = Country.Japan 197 | } 198 | }; 199 | } 200 | 201 | private bool CalculateDiscountRate(Product product) 202 | { 203 | product.DiscountRate = 0.15F; 204 | return true; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sonar-Kule 2 | 3 | Teknik borcun oluşturduğu problemlerden kurtulmanın önemli adımlarından birisi yüksek kalitede kod yazabilmektir. Aynı problemi çözmek için birden fazla yol olduğundan ortak standartlarda buluşmak önemlidir. Eskiden kod yazma standartlarına ilişkin dokümanları kullanırdık. Ancak günümüzün gelişmiş IDE'leri ve uygulama geliştirme platformları, ideal kodlama için gerekli uyarıları zaten vermekte. Elbette kod tabanı çok eskiye dayanan sistemlerde bu yeterli olmayabilir. Hatta CI hattında koşacak bir kod kontrol aracı, teknik borç oluşmadan kaliteyi kontrol altına almamızı garanti edebilir. Daha önceden .Net Framework tarafında SonarQube kullanımını ele almak için [Project-Denver](https://github.com/buraksenyurt/project-denver) isimli legacy bir kobay projeyi ele almıştım. Bu repoda ise güncel .Net platformunda kullanımını inceleyip sıklıkla yapılan C# kod ihlallerini incelemeye çalışacağım. 4 | 5 | - [Sonar-Kule](#sonar-kule) 6 | - [Amaç](#amaç) 7 | - [Branch Stratejisi](#branch-stratejisi) 8 | - [Ön Hazırlıklar](#ön-hazırlıklar) 9 | - [Sonarqube Tarafında Proje Oluşturulması](#sonarqube-tarafında-proje-oluşturulması) 10 | - [\[DAY 1\] Solution Oluşturulması ve İlk Çıktılar](#day-1-solution-oluşturulması-ve-i̇lk-çıktılar) 11 | - [\[DAY 2\]](#day-2) 12 | - [\[DAY 3\]](#day-3) 13 | - [\[DAY 4\]](#day-4) 14 | - [Bundan Sonrası](#bundan-sonrası) 15 | 16 | ## Amaç 17 | 18 | Öncelikle uygulamanın belli bir ürün veya çözüm sunmadığını belirteyim. İlk olarak olabildiğince fazla sayıda teknik borç biriktiren ama build olan bir kod tabanı oluşturmayı hedefliyoruz. Ardından Sonarqube ihlallerini analiz edip, nasıl çözümler uygulanması gerektiği üzerine durmayı planlıyoruz. Bu anlamda projenin dev branch'i kirli kodları barındıran bir yapıya sahip ve istenen seviyeye gelene kadar da üzerinde düzeltmeler yapılmayacak. 19 | 20 | ## Branch Stratejisi 21 | 22 | Dev branch'inde yer alan kodları düzenli olarak Main branch'e de alıyorum. Main'i üretim ortamı gibi düşünebiliriz. Local ortamda SonarQube'a dev branch'ini taratmaktayız. Bu nedenle düzeltme çalışmalarına başlamadan önce Dev'in kusurlu olan ve ilerleyen zamanlardaki lablarda kullanılabilecek versiyonunu ayrı bir feature'a taşımak güzel olabilir _(fItsInTrouble isimli bir feature mesela)_ 23 | 24 | ## Ön Hazırlıklar 25 | 26 | Örnekleri Ubuntu 22.04 sistemimde deniyorum. Sistemde .Net 7 sürümü yüklü. Normalde bir Sonarqube sunucusuna ihtiyacımız olur ancak resmi [dokümantasyonda](https://docs.sonarqube.org/9.7/setup-and-upgrade/install-the-server/) güzel bir docker-compose dosyası var. Dolayısıyla sistemde docker yüklü ise fazla zahmete girmeden sonarqube denemelerine başlanabilir. 27 | 28 | ```bash 29 | # Kendi ubuntu sistemimde bu imajı denerken 30 | # bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 31 | # şeklinde bir hata aldım. 32 | # Bu nedenle aşağıdaki komutla istenen bellek aranını artırdım. Tabii makinenin fanı biraz bağırmaya başladı :D 33 | sysctl -w vm.max_map_count=262144 34 | 35 | sudo docker-compose up 36 | ``` 37 | 38 | Bu işlemlerin ardından Moon'da, localhost:9000 adresine girdiğimde Sonarqube'e erişebildiğimi gördüm. 39 | 40 | ![assets/sonar_runtime_01.png](assets/sonar_runtime_01.png) 41 | 42 | ## Sonarqube Tarafında Proje Oluşturulması 43 | 44 | Kod tarafının taramasını başlatmadan önce, ölçümlerin yollanacağı bir projenin SonarQube tarafında oluşturulması gerekiyor. Yeni arabirimdeki seçeneklere göre github, gitlab, bitbucket, azure vb kod repolarını seçmemiz mümkün. Ben Manually seçeneği ile ilerliyorum. Burada hangi branch ile çalışacağımız da önemli. Çalışmada ihlaller içeren bir kod tabanına ihtiyacımız var. Bunların dev isimli bir branch'te toplandığını düşünebiliriz. 45 | 46 | ![assets/sonar_runtime_02.png](assets/sonar_runtime_02.png) 47 | 48 | Bu adımdan sonra bazı seçenekler gelecektir. Locally ile devam edebiliriz. Ve sonrasında aşağıdaki seçimlerle devam edebiliriz. 49 | 50 | ![assets/sonar_runtime_03.png](assets/sonar_runtime_03.png) 51 | 52 | Bu kısımca bir key üretilir. Bu key bilgisi komut satırından yapacağımız taramalar için de gerekli olacaktır. 53 | 54 | ![assets/sonar_runtime_04.png](assets/sonar_runtime_04.png) 55 | 56 | Şimdi hangi platform için bu projeyi kullanacağımızı belirtiyoruz. .Net platformunu ve ardından .Net Core'u seçmemiz bu çalışma için yeterli. Kalan kısımda SonarQube neler yapmamız gerektiğini zaten adım adım tarifliyor. 57 | 58 | ![assets/sonar_runtime_05.png](assets/sonar_runtime_05.png) 59 | 60 | Komut satırından tarama işlemini başlatmak için dotnet-sonarscanner aracını global olarak yükleyebiliriz. Ardından proje klasöründe yine dokümanın bizim için hazırladığı komutları çalıştırmak yeterli olacaktır. 61 | 62 | ```bash 63 | # Tool install adımı 64 | dotnet tool install --global dotnet-sonarscanner 65 | 66 | # projenin root klasöründe dev branch'indeyken çalıştıracağımız komut 67 | # tabii key değerleri benim sistemim için üretilmiştir. Siz kendi sisteminizde üretilen proje adı ve key değerlerini kullanmalısınız. 68 | dotnet sonarscanner begin /k:"sonar-kule-qa-project-1976" /d:sonar.host.url="http://localhost:9000" /d:sonar.login="sqp_153a6591e678e112bba3f6e4d11c7d7bd0643df5" 69 | # Tarayıcıyı başlattıktan sonra projeyi build ederiz 70 | dotnet build 71 | # ve tarama işleminin sonlandırılması komutunu veririz 72 | dotnet sonarscanner end /d:sonar.login="sqp_153a6591e678e112bba3f6e4d11c7d7bd0643df5" 73 | ``` 74 | 75 | ## [DAY 1] Solution Oluşturulması ve İlk Çıktılar 76 | 77 | Deneme amaçlı bir Solution geliştiriyoruz. Dev branch'te çalışmaya özen gösteriyorum. Normalde derlenebilir bir proje ama kod tarafında saçmalamaya çalıştığım bir sürü yer var. Sırf sonar'a iş çıkarmak için. Keh keh key...Başlangıç açısından bu şekilde tarama yapmak önemli. Yeni kodlar ekledikçe biraz daha teknik borcu yükseltmeye ve çeşitlendirmeye çalışabiliriz. 30 günlük bir süre içerisinde de ilerleyişimizi görürüz. İlk sonuçlar şöyle gerçekleşmiştir. 78 | 79 | ![assets/sonar_runtime_06.png](assets/sonar_runtime_06.png) 80 | 81 | Daha şimdiden çoraplar kokmaya başladı... Iyyyykkk! :P 82 | 83 | ![assets/sonar_runtime_07.png](assets/sonar_runtime_07.png) 84 | 85 | Hatta bilerek yazdığımız güvenlik açıkları da yakalanır. 86 | 87 | ![assets/sonar_runtime_08.png](assets/sonar_runtime_08.png) 88 | 89 | ## [DAY 2] 90 | 91 | Kodda saçmalamaya devam edip build olan ama teknik borç yükünün artmasına neden olan eklemeler sonrasındaki durum ise şöyle olacaktır. Yeni eklenen kodlarla 3 yeni bug'ımız var ve teknik borcu temizleme süremiz 54 dakika. Kokan çorapların sayısı ise 30. Code Coverage oranımız 0. Yani test edilebilir bir kod tabanımız bulunmuyor. 92 | 93 | ![assets/sonar_runtime_09.png](assets/sonar_runtime_09.png) 94 | 95 | Genel resme baktığımızda teknik borcu temizleme süresinin neredeyse 1.5 saate çıktığını kokan çorap sayısının 49 olduğunu ve en kötüsü de güvenlik sınavından E aldığımızı görebiliriz. Kodun güvenilirlik notu ise C. 96 | 97 | ![assets/sonar_runtime_10.png](assets/sonar_runtime_10.png) 98 | 99 | Issue'ların sayısında da artış var ve Critical olarak kategorilendirilmiş bir tanesi de meşhur Cognitive Complexity değeri 15'i aşan fonksiyonlar. Bir tane üretmeyi başardım :D 100 | 101 | ![assets/sonar_runtime_11.png](assets/sonar_runtime_11.png) 102 | 103 | ## [DAY 3] 104 | 105 | Üçüncü günün şafağında teknik borç biraz daha artmış oldu. Bu sefer özellikle tekrarlı kodları artırmaya da çalıştım. 106 | 107 | ![assets/sonar_runtime_12.png](assets/sonar_runtime_12.png) 108 | 109 | ![assets/sonar_runtime_15.png](assets/sonar_runtime_15.png) 110 | 111 | ![assets/sonar_runtime_13.png](assets/sonar_runtime_13.png) 112 | 113 | ![assets/sonar_runtime_14.png](assets/sonar_runtime_14.png) 114 | 115 | ## [DAY 4] 116 | 117 | 4ncü günde de kodda tutarlı şekilde saçmalayarak teknik borcu artırmaya çalıştım. Yeni eklenen kodlar için güncel rapor özeti şöyle. 118 | 119 | ![assets/sonar_runtime_16.png](assets/sonar_runtime_16.png) 120 | 121 | ve son taramaya göre tüm kod tabanının durumu aşağıdaki gibi. Teknik borcu temizleme süresi epeyce artıyor. 122 | 123 | ![assets/sonar_runtime_17.png](assets/sonar_runtime_17.png) 124 | 125 | ## Bundan Sonrası 126 | 127 | Aslında projenin bundan sonraki kısımlarında teknik borcu artıracak hamleler yapmaya devam edebiliriz ancak var olan durumu gözden geçirip borçları temizleyerer ilerlemek en güzeli. 128 | 129 | _KENDİME NOT : Bu bir Youtube video anlatımı ile pek güzel yorumlanabilir._ 130 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | .sonarqube/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.tlog 95 | *.vspscc 96 | *.vssscc 97 | .builds 98 | *.pidb 99 | *.svclog 100 | *.scc 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 299 | *.vbp 300 | 301 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 302 | *.dsw 303 | *.dsp 304 | 305 | # Visual Studio 6 technical files 306 | *.ncb 307 | *.aps 308 | 309 | # Visual Studio LightSwitch build output 310 | **/*.HTMLClient/GeneratedArtifacts 311 | **/*.DesktopClient/GeneratedArtifacts 312 | **/*.DesktopClient/ModelManifest.xml 313 | **/*.Server/GeneratedArtifacts 314 | **/*.Server/ModelManifest.xml 315 | _Pvt_Extensions 316 | 317 | # Paket dependency manager 318 | .paket/paket.exe 319 | paket-files/ 320 | 321 | # FAKE - F# Make 322 | .fake/ 323 | 324 | # CodeRush personal settings 325 | .cr/personal 326 | 327 | # Python Tools for Visual Studio (PTVS) 328 | __pycache__/ 329 | *.pyc 330 | 331 | # Cake - Uncomment if you are using it 332 | # tools/** 333 | # !tools/packages.config 334 | 335 | # Tabs Studio 336 | *.tss 337 | 338 | # Telerik's JustMock configuration file 339 | *.jmconfig 340 | 341 | # BizTalk build output 342 | *.btp.cs 343 | *.btm.cs 344 | *.odx.cs 345 | *.xsd.cs 346 | 347 | # OpenCover UI analysis results 348 | OpenCover/ 349 | 350 | # Azure Stream Analytics local run output 351 | ASALocalRun/ 352 | 353 | # MSBuild Binary and Structured Log 354 | *.binlog 355 | 356 | # NVidia Nsight GPU debugger configuration file 357 | *.nvuser 358 | 359 | # MFractors (Xamarin productivity tool) working folder 360 | .mfractor/ 361 | 362 | # Local History for Visual Studio 363 | .localhistory/ 364 | 365 | # Visual Studio History (VSHistory) files 366 | .vshistory/ 367 | 368 | # BeatPulse healthcheck temp database 369 | healthchecksdb 370 | 371 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 372 | MigrationBackup/ 373 | 374 | # Ionide (cross platform F# VS Code tools) working folder 375 | .ionide/ 376 | 377 | # Fody - auto-generated XML schema 378 | FodyWeavers.xsd 379 | 380 | # VS Code files for those working on multiple tools 381 | .vscode/* 382 | !.vscode/settings.json 383 | !.vscode/tasks.json 384 | !.vscode/launch.json 385 | !.vscode/extensions.json 386 | *.code-workspace 387 | 388 | # Local History for Visual Studio Code 389 | .history/ 390 | 391 | # Windows Installer files from build outputs 392 | *.cab 393 | *.msi 394 | *.msix 395 | *.msm 396 | *.msp 397 | 398 | # JetBrains Rider 399 | *.sln.iml 400 | -------------------------------------------------------------------------------- /BusinessLib/Ordering.cs: -------------------------------------------------------------------------------- 1 | using ModelLib; 2 | using CommonLib; 3 | using RepositoryLib; 4 | using CommonLib.Exceptions; 5 | using System.Text.Json; 6 | 7 | namespace BusinessLib; 8 | 9 | public class Ordering 10 | { 11 | private FileLogger _logger = new FileLogger(); 12 | private NorthwindDbContext _context; 13 | public Ordering() 14 | { 15 | _context = new NorthwindDbContext(); 16 | } 17 | private bool CalculateDiscountRate(Product product) 18 | { 19 | product.DiscountRate = 0.15F; 20 | return true; 21 | } 22 | private ShipmentCompany GetShipmentCompanyFromCity(string city) 23 | { 24 | return _context.ShipmentCompanies.Where(c => c.ServedCities.Any(sc => sc.Name == city)).SingleOrDefault(); 25 | } 26 | private CustomerStatus CheckCustomerStatus(Customer customer, PaymentType paymentType, Product product) 27 | { 28 | if (!customer.IsSuspicious) 29 | { 30 | switch (paymentType) 31 | { 32 | case PaymentType.CreditCard: 33 | case PaymentType.DebitCard: 34 | case PaymentType.Cash: 35 | return CustomerStatus.Available; 36 | break; 37 | default: 38 | return CustomerStatus.Declined; 39 | } 40 | } 41 | else 42 | { 43 | return CustomerStatus.Declined; 44 | } 45 | } 46 | public bool AddOrdersToProductAndStartShipments(int productId, Order[] orders) 47 | { 48 | bool result = false; 49 | Product product = null; 50 | try 51 | { 52 | product = _context.GetProduct(productId); 53 | if (product.CategoryId == 3) 54 | { 55 | if (!product.OnSales || product.StockLevel < 10) 56 | { 57 | return false; 58 | } 59 | } 60 | 61 | var calcResult = CalculateDiscountRate(product); 62 | if (!calcResult) 63 | { 64 | return false; 65 | } 66 | 67 | product.Orders = new Order[orders.Length]; 68 | var index = 0; 69 | foreach (var order in orders) 70 | { 71 | switch (order.Customer.MemberType) 72 | { 73 | case MemberType.Regular: 74 | break; 75 | case MemberType.Gold: 76 | product.DiscountRate += 0.1F; 77 | break; 78 | case MemberType.Platinium: 79 | product.DiscountRate += 0.1F; 80 | break; 81 | } 82 | product.Orders[index] = order; 83 | 84 | switch (order.Customer.City) 85 | { 86 | case "Istanbul": 87 | order.ShipmentCompany = GetShipmentCompanyFromCity(order.Customer.City); 88 | break; 89 | case "Tokyo": 90 | order.ShipmentCompany = GetShipmentCompanyFromCity(order.Customer.City); 91 | break; 92 | case "New York": 93 | order.ShipmentCompany = new ShipmentCompany 94 | { 95 | CompanyId = 1, 96 | Country = Country.USA, 97 | Level = 950, 98 | Name = "YupPiiEss" 99 | }; 100 | break; 101 | case "Berlin": 102 | order.ShipmentCompany = new ShipmentCompany 103 | { 104 | CompanyId = 1, 105 | Country = Country.Australia, 106 | Level = 1000, 107 | Name = "Doyçe Postal" 108 | }; 109 | break; 110 | default: 111 | break; 112 | } 113 | 114 | if (order.PaymentType == PaymentType.DigitalCoin) 115 | { 116 | if (CheckCustomerStatus(order.Customer, order.PaymentType, product) == CustomerStatus.Declined) 117 | { 118 | return false; 119 | } 120 | } 121 | Waybill waybill = new Waybill 122 | { 123 | Address = order.DestinationAddress, 124 | CustomerFullName = order.Customer.Name + " " + order.Customer.MiddleName + " " + order.Customer.LastName, 125 | Date = DateTime.Now, 126 | PaymentType = order.PaymentType, 127 | OrderId = order.OrderId 128 | }; 129 | 130 | var notificationAddress = "https://nowhere.com/api/governecy/waybill_management"; 131 | var apiKey = "123456789987654321"; 132 | var apiPass = "P@ssw0rd"; 133 | GovermentIntegrator integrator = new GovermentIntegrator(notificationAddress); 134 | var isConnected = integrator.Connect(apiKey, apiPass); 135 | if (isConnected) 136 | { 137 | IntegratorResponse sendResponse = integrator.PostWaybill(waybill); 138 | if (sendResponse.Status != IntegratorStatus.Success) 139 | { 140 | _logger.WarnAsync("Unsuccess the integrator calll", "AddOrdersToProductAndStartShipments Function"); 141 | return false; 142 | } 143 | else 144 | { 145 | if (sendResponse.Status == IntegratorStatus.FraudDetected) 146 | { 147 | _logger.WarnAsync("Fraud detected", "AddOrdersToProductAndStartShipments Function"); 148 | order.Customer.IsSuspicious = true; 149 | } 150 | } 151 | } 152 | else 153 | { 154 | //TODO Must logged this status 155 | throw new IntegratorException("Could not connect to Integrator"); 156 | return false; 157 | } 158 | index++; 159 | } 160 | } 161 | catch (Exception excp) 162 | { 163 | throw new ShippingException(); 164 | } 165 | 166 | return true; 167 | } 168 | 169 | public async Task GetSalaryReportByMonth(Month month) 170 | { 171 | try 172 | { 173 | string reportPath = "http://izmprsrv01/reports/api/salary/" + month.ToString(); 174 | HttpClient client = new HttpClient(); 175 | HttpResponseMessage responseMessage = await client.GetAsync(reportPath); 176 | var body = await responseMessage.Content.ReadAsStringAsync(); 177 | var report = JsonSerializer.Deserialize(body); 178 | string result = @" 179 | 180 | 181 |

" + month.ToString() + @" AYLIK RAPORU

182 | 183 | 186 | 189 | 192 | 193 | 194 | 195 | 198 | 200 | 201 |
184 | TotalSalary 185 | 187 | AverageSalaryPerDaily 188 | 190 | TotalUnit 191 |
" + report.TotalSalary.ToString("C2") + @" 196 | " + report.AverageSalaryPerDaily.ToString("C2") + @" 197 | " 199 | + report.TotalUnit.ToString() + @"
202 | 203 | 204 | "; 205 | 206 | return result; 207 | } 208 | catch (Exception excp) 209 | { 210 | throw new ReportException(); 211 | } 212 | } 213 | } 214 | 215 | public enum CustomerStatus 216 | { 217 | Available, 218 | Declined 219 | } 220 | 221 | public class Report 222 | { 223 | public decimal TotalSalary { get; set; } 224 | public decimal AverageSalaryPerDaily { get; set; } 225 | public int TotalUnit { get; set; } 226 | public int AverageUnitPerDaily { get; set; } 227 | } 228 | 229 | public enum Month 230 | { 231 | Jan, 232 | Feb, 233 | Mar, 234 | Apr, 235 | May, 236 | Jun, 237 | Jul, 238 | Aug, 239 | Sep, 240 | Oct, 241 | Now, 242 | Dec 243 | } 244 | --------------------------------------------------------------------------------