From 59092db8991388a8332ac5adb68951b927d36e8d Mon Sep 17 00:00:00 2001 From: ereshkigal Date: Sat, 2 Nov 2024 23:22:40 +0300 Subject: [PATCH 1/7] Initialized openAPI service --- OpenApiService/OpenApiService.csproj | 9 +++++ OpenApiService/OpenApiService.sln | 25 ++++++++++++ OpenApiService/Program.cs | 6 +++ OpenApiService/Properties/launchSettings.json | 38 +++++++++++++++++++ OpenApiService/appsettings.json | 9 +++++ TourService/Database/ApplicationContext.cs | 5 --- .../Database/Models/EntartainmentWish.cs | 21 ---------- TourService/Database/Models/Entertainment.cs | 17 --------- TourService/Database/Models/PaymentMethod.cs | 19 ---------- TourService/Database/Models/PaymentVariant.cs | 19 ---------- TourService/Database/Models/Tour.cs | 4 ++ .../Database/Models/TourPaymentMethod.cs | 23 ----------- .../DeleteBucketException.cs | 2 +- .../StorageUnavailibleException.cs | 2 +- .../Tours/Responses/GetToursResponse.cs | 14 +++++++ TourService/appsettings.Development.json | 5 ++- TourService/appsettings.json | 5 +-- 17 files changed, 112 insertions(+), 111 deletions(-) create mode 100644 OpenApiService/OpenApiService.csproj create mode 100644 OpenApiService/OpenApiService.sln create mode 100644 OpenApiService/Program.cs create mode 100644 OpenApiService/Properties/launchSettings.json create mode 100644 OpenApiService/appsettings.json delete mode 100644 TourService/Database/Models/EntartainmentWish.cs delete mode 100644 TourService/Database/Models/Entertainment.cs delete mode 100644 TourService/Database/Models/PaymentMethod.cs delete mode 100644 TourService/Database/Models/PaymentVariant.cs delete mode 100644 TourService/Database/Models/TourPaymentMethod.cs create mode 100644 TourService/Models/Tours/Responses/GetToursResponse.cs diff --git a/OpenApiService/OpenApiService.csproj b/OpenApiService/OpenApiService.csproj new file mode 100644 index 0000000..1b28a01 --- /dev/null +++ b/OpenApiService/OpenApiService.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/OpenApiService/OpenApiService.sln b/OpenApiService/OpenApiService.sln new file mode 100644 index 0000000..0d3b7d5 --- /dev/null +++ b/OpenApiService/OpenApiService.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiService", "OpenApiService.csproj", "{BE27ECAB-7EF8-4078-9691-A235B3180806}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BE27ECAB-7EF8-4078-9691-A235B3180806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE27ECAB-7EF8-4078-9691-A235B3180806}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE27ECAB-7EF8-4078-9691-A235B3180806}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE27ECAB-7EF8-4078-9691-A235B3180806}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BE71147F-EC84-4E4B-8B98-2857214C0405} + EndGlobalSection +EndGlobal diff --git a/OpenApiService/Program.cs b/OpenApiService/Program.cs new file mode 100644 index 0000000..1760df1 --- /dev/null +++ b/OpenApiService/Program.cs @@ -0,0 +1,6 @@ +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.MapGet("/", () => "Hello World!"); + +app.Run(); diff --git a/OpenApiService/Properties/launchSettings.json b/OpenApiService/Properties/launchSettings.json new file mode 100644 index 0000000..9930d0d --- /dev/null +++ b/OpenApiService/Properties/launchSettings.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:22740", + "sslPort": 44369 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5074", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7101;http://localhost:5074", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/OpenApiService/appsettings.json b/OpenApiService/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/OpenApiService/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/TourService/Database/ApplicationContext.cs b/TourService/Database/ApplicationContext.cs index c71c42c..9dd46b2 100644 --- a/TourService/Database/ApplicationContext.cs +++ b/TourService/Database/ApplicationContext.cs @@ -11,8 +11,6 @@ public class ApplicationContext : DbContext { public DbSet Benefits { get; set; } public DbSet Categories { get; set; } - public DbSet EntartaimentWishes { get; set; } - public DbSet Entertaiments { get; set; } public DbSet Photos { get; set; } public DbSet Reviews { get; set; } public DbSet ReviewBenefits { get; set; } @@ -20,9 +18,6 @@ public class ApplicationContext : DbContext public DbSet Tours { get; set; } public DbSet TourCategories { get; set; } public DbSet TourWishes { get; set; } - public DbSet TourPaymentMethods { get; set;} - public DbSet PaymentMethods { get; set; } - public DbSet PaymentVariants { get; set; } public ApplicationContext(DbContextOptions options) : base(options) { Database.EnsureCreated(); diff --git a/TourService/Database/Models/EntartainmentWish.cs b/TourService/Database/Models/EntartainmentWish.cs deleted file mode 100644 index cbf1854..0000000 --- a/TourService/Database/Models/EntartainmentWish.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Database.Models -{ - public class EntartainmentWish - { - [Key] - public long Id {get;set;} - [Required] - public long UserId {get;set;} - [ForeignKey("EntertaimentId")] - public long EntertaimentId {get;set;} - [Required] - public Entertainment Entertaiment {get;set;} = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Entertainment.cs b/TourService/Database/Models/Entertainment.cs deleted file mode 100644 index bcc0b2d..0000000 --- a/TourService/Database/Models/Entertainment.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Entertainment - { - [Key] - public long Id {get;set;} - [TourName] - public string Name {get;set;} = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/PaymentMethod.cs b/TourService/Database/Models/PaymentMethod.cs deleted file mode 100644 index 6fa2aae..0000000 --- a/TourService/Database/Models/PaymentMethod.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class PaymentMethod - { - [Key] - public long Id { get; set; } - [Required] - [TourName] - public string Name { get; set; } = null!; - public ICollection? PaymentVariants { get; set; } - } -} \ No newline at end of file diff --git a/TourService/Database/Models/PaymentVariant.cs b/TourService/Database/Models/PaymentVariant.cs deleted file mode 100644 index 61981f0..0000000 --- a/TourService/Database/Models/PaymentVariant.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class PaymentVariant - { - [Key] - public long Id { get; set; } - [Required] - public string Name { get; set; } = null!; - [TourPrice] - public double Price { get; set; } - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Tour.cs b/TourService/Database/Models/Tour.cs index 01e83c8..ab8ab04 100644 --- a/TourService/Database/Models/Tour.cs +++ b/TourService/Database/Models/Tour.cs @@ -28,6 +28,10 @@ public class Tour public bool IsActive { get; set; } [Text] public string Comment { get; set;} = null!; + [Required] + public DateTime BeginDate { get; set; } + [Required] + public DateTime EndDate { get; set; } public ICollection? Photos { get; set; } public ICollection? Reviews { get; set; } } diff --git a/TourService/Database/Models/TourPaymentMethod.cs b/TourService/Database/Models/TourPaymentMethod.cs deleted file mode 100644 index 232b13b..0000000 --- a/TourService/Database/Models/TourPaymentMethod.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Database.Models -{ - public class TourPaymentMethod - { - [Key] - public long Id { get; set; } - [ForeignKey("TourId")] - public long TourId { get; set; } - [Required] - public Tour Tour { get; set; } = null!; - [ForeignKey("PaymentMethodId")] - public long PaymentMethodId { get; set; } - [Required] - public PaymentMethod PaymentMethod{ get; set; } = null!; - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs b/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs index 3d2cf59..2997a79 100644 --- a/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs +++ b/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs @@ -1,4 +1,4 @@ -namespace ImageAgregationService.Exceptions.S3ServiceExceptions +namespace TourService.Exceptions.S3ServiceExceptions { [System.Serializable] public class DeleteBucketException : System.Exception diff --git a/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs b/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs index 7b38c1c..9bd7995 100644 --- a/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs +++ b/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs @@ -1,4 +1,4 @@ -namespace ImageAgregationService.Exceptions.S3ServiceExceptions +namespace TourService.Exceptions.S3ServiceExceptions { [System.Serializable] public class StorageUnavailibleException : System.Exception diff --git a/TourService/Models/Tours/Responses/GetToursResponse.cs b/TourService/Models/Tours/Responses/GetToursResponse.cs new file mode 100644 index 0000000..d09e42f --- /dev/null +++ b/TourService/Models/Tours/Responses/GetToursResponse.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; +using TourService.Database.Models; + +namespace TourService.Models.Tours.Responses +{ + public class GetToursResponse + { + + } +} \ No newline at end of file diff --git a/TourService/appsettings.Development.json b/TourService/appsettings.Development.json index 0c208ae..578f901 100644 --- a/TourService/appsettings.Development.json +++ b/TourService/appsettings.Development.json @@ -4,5 +4,8 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } - } + }, + "Buckets":[ + { "BucketName": "TourImages", "BucketId": "d3b3c1e0-1c2e-4f3b-8c1e-1b2c3d4e5f6g" } + ] } diff --git a/TourService/appsettings.json b/TourService/appsettings.json index 5fb28bc..77167f0 100644 --- a/TourService/appsettings.json +++ b/TourService/appsettings.json @@ -5,9 +5,6 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*", - "Buckets":[ - { "BucketName": "TourImages", "BucketId": "d3b3c1e0-1c2e-4f3b-8c1e-1b2c3d4e5f6g" } - ] + "AllowedHosts": "*" } From 5f1eb39cddb34afe2420f36126a1832fb7f2a6f3 Mon Sep 17 00:00:00 2001 From: ereshkigal Date: Sat, 2 Nov 2024 23:26:43 +0300 Subject: [PATCH 2/7] removing service accidentally added to this branch --- .../Attributes/Validation/Coordinates.cs | 47 ---- .../Attributes/Validation/Description.cs | 49 ---- TourService/Attributes/Validation/FileLink.cs | 44 --- TourService/Attributes/Validation/Rating.cs | 38 --- TourService/Attributes/Validation/Text.cs | 53 ---- .../Attributes/Validation/TourAddress.cs | 55 ---- TourService/Attributes/Validation/TourName.cs | 42 --- .../Attributes/Validation/TourPrice.cs | 28 -- TourService/Database/ApplicationContext.cs | 30 -- TourService/Database/Models/Benefit.cs | 17 -- TourService/Database/Models/Category.cs | 17 -- TourService/Database/Models/Photo.cs | 17 -- TourService/Database/Models/Review.cs | 25 -- TourService/Database/Models/ReviewBenefit.cs | 23 -- TourService/Database/Models/Tag.cs | 17 -- TourService/Database/Models/Tour.cs | 38 --- TourService/Database/Models/TourCategory.cs | 23 -- TourService/Database/Models/TourWish.cs | 21 -- .../BucketNotFoundException.cs | 10 - .../ConfigureBucketsException.cs | 9 - .../DeleteBucketException.cs | 10 - .../DeleteImageException.cs | 10 - .../S3ServiceExceptions/GetImageException.cs | 10 - .../ImageNotFoundException.cs | 9 - .../StorageUnavailibleException.cs | 10 - .../UploadImageException.cs | 9 - TourService/Kafka/KafkaRequestService.cs | 259 ------------------ TourService/Kafka/KafkaService.cs | 121 -------- TourService/Kafka/KafkaTopicManager.cs | 74 ----- TourService/Kafka/Utils/MethodKeyPair.cs | 13 - TourService/Kafka/Utils/PendingMessagesBus.cs | 15 - .../Kafka/Utils/RecievedMessagesBus.cs | 14 - .../ConfigureConsumersException.cs | 15 - .../ConfigureMessageBusException.cs | 15 - .../ConsumerException/ConsumerException.cs | 18 -- ...ConsumerRecievedMessageInvalidException.cs | 18 -- .../ConsumerTopicUnavailableException.cs | 18 -- .../KafkaException/MyKafkaException.cs | 21 -- .../MessageProduceException.cs | 18 -- .../ProducerExceptions/ProducerException.cs | 21 -- .../TopicExceptions/CheckTopicException.cs | 18 -- .../TopicExceptions/CreateTopicException.cs | 18 -- .../TopicExceptions/TopicException.cs | 18 -- .../Tours/Responses/GetToursResponse.cs | 14 - TourService/Program.cs | 6 - TourService/Properties/launchSettings.json | 38 --- TourService/Repository/FindOptions.cs | 8 - TourService/Repository/IRepository.cs | 18 -- TourService/Repository/Repository.cs | 79 ------ TourService/Services/S3/IS3Service.cs | 20 -- TourService/Services/S3/S3Service.cs | 206 -------------- TourService/TourService.csproj | 32 --- TourService/TourService.sln | 25 -- TourService/Utils/Logging.cs | 40 --- TourService/Utils/Models/Bucket.cs | 13 - TourService/appsettings.Development.json | 11 - TourService/appsettings.json | 10 - 57 files changed, 1875 deletions(-) delete mode 100644 TourService/Attributes/Validation/Coordinates.cs delete mode 100644 TourService/Attributes/Validation/Description.cs delete mode 100644 TourService/Attributes/Validation/FileLink.cs delete mode 100644 TourService/Attributes/Validation/Rating.cs delete mode 100644 TourService/Attributes/Validation/Text.cs delete mode 100644 TourService/Attributes/Validation/TourAddress.cs delete mode 100644 TourService/Attributes/Validation/TourName.cs delete mode 100644 TourService/Attributes/Validation/TourPrice.cs delete mode 100644 TourService/Database/ApplicationContext.cs delete mode 100644 TourService/Database/Models/Benefit.cs delete mode 100644 TourService/Database/Models/Category.cs delete mode 100644 TourService/Database/Models/Photo.cs delete mode 100644 TourService/Database/Models/Review.cs delete mode 100644 TourService/Database/Models/ReviewBenefit.cs delete mode 100644 TourService/Database/Models/Tag.cs delete mode 100644 TourService/Database/Models/Tour.cs delete mode 100644 TourService/Database/Models/TourCategory.cs delete mode 100644 TourService/Database/Models/TourWish.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/BucketNotFoundException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/ConfigureBucketsException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/DeleteImageException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/GetImageException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/ImageNotFoundException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs delete mode 100644 TourService/Exceptions/S3ServiceExceptions/UploadImageException.cs delete mode 100644 TourService/Kafka/KafkaRequestService.cs delete mode 100644 TourService/Kafka/KafkaService.cs delete mode 100644 TourService/Kafka/KafkaTopicManager.cs delete mode 100644 TourService/Kafka/Utils/MethodKeyPair.cs delete mode 100644 TourService/Kafka/Utils/PendingMessagesBus.cs delete mode 100644 TourService/Kafka/Utils/RecievedMessagesBus.cs delete mode 100644 TourService/KafkaException/ConfigurationException/ConfigureConsumersException.cs delete mode 100644 TourService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs delete mode 100644 TourService/KafkaException/ConsumerException/ConsumerException.cs delete mode 100644 TourService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs delete mode 100644 TourService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs delete mode 100644 TourService/KafkaException/MyKafkaException.cs delete mode 100644 TourService/KafkaException/ProducerExceptions/MessageProduceException.cs delete mode 100644 TourService/KafkaException/ProducerExceptions/ProducerException.cs delete mode 100644 TourService/KafkaException/TopicExceptions/CheckTopicException.cs delete mode 100644 TourService/KafkaException/TopicExceptions/CreateTopicException.cs delete mode 100644 TourService/KafkaException/TopicExceptions/TopicException.cs delete mode 100644 TourService/Models/Tours/Responses/GetToursResponse.cs delete mode 100644 TourService/Program.cs delete mode 100644 TourService/Properties/launchSettings.json delete mode 100644 TourService/Repository/FindOptions.cs delete mode 100644 TourService/Repository/IRepository.cs delete mode 100644 TourService/Repository/Repository.cs delete mode 100644 TourService/Services/S3/IS3Service.cs delete mode 100644 TourService/Services/S3/S3Service.cs delete mode 100644 TourService/TourService.csproj delete mode 100644 TourService/TourService.sln delete mode 100644 TourService/Utils/Logging.cs delete mode 100644 TourService/Utils/Models/Bucket.cs delete mode 100644 TourService/appsettings.Development.json delete mode 100644 TourService/appsettings.json diff --git a/TourService/Attributes/Validation/Coordinates.cs b/TourService/Attributes/Validation/Coordinates.cs deleted file mode 100644 index cfb9e3d..0000000 --- a/TourService/Attributes/Validation/Coordinates.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class Coordinates : ValidationAttribute - { - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - var coordinateString = value.ToString()!; - var parts = coordinateString.Split(','); - - if (parts.Length != 2) - { - return false; - } - - if (double.TryParse(parts[0].Trim(), out double latitude) && - double.TryParse(parts[1].Trim(), out double longitude)) - { - if (latitude < -90 || latitude > 90) - { - return false; - } - - if (longitude < -180 || longitude > 180) - { - return false; - } - - return true; - } - - return false; - } - } - -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/Description.cs b/TourService/Attributes/Validation/Description.cs deleted file mode 100644 index 08cdca5..0000000 --- a/TourService/Attributes/Validation/Description.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class Description : ValidationAttribute - { - private static readonly string[] ProhibitedWords = - { - "admin", "administrator", "root" - }; - - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - var description = value.ToString()!; - - if (string.IsNullOrWhiteSpace(description)) - { - return false; - } - - if (!Regex.IsMatch(description, @"^[а-яА-ЯёЁa-zA-Z0-9\s\.\,\!\?\""\-]+$")) - { - return false; - } - - foreach (var word in ProhibitedWords) - { - if (description.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) - { - return false; - } - } - - return true; - } - - } -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/FileLink.cs b/TourService/Attributes/Validation/FileLink.cs deleted file mode 100644 index 3dcb4e6..0000000 --- a/TourService/Attributes/Validation/FileLink.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class FileLink : ValidationAttribute - { - private static readonly string[] ProhibitedWords = { "admin", "administrator", "root"}; - - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - var fileLink = value.ToString()!; - - if (string.IsNullOrWhiteSpace(fileLink) || - !Regex.IsMatch(fileLink, @"^(http|https)://[^\s/$.?#].[^\s]*$")) - { - return false; - } - - foreach (var word in ProhibitedWords) - { - if (fileLink.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) - { - return false; - } - } - - return true; - } - - - } -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/Rating.cs b/TourService/Attributes/Validation/Rating.cs deleted file mode 100644 index 0865ed6..0000000 --- a/TourService/Attributes/Validation/Rating.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class Rating : ValidationAttribute - { - private readonly int _min; - private readonly int _max; - - public Rating(int min = 1, int max = 5) - { - _min = min; - _max = max; - } - - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - if (value is int rating) - { - return rating >= _min && rating <= _max; - } - - return false; - } - - - } -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/Text.cs b/TourService/Attributes/Validation/Text.cs deleted file mode 100644 index d60b353..0000000 --- a/TourService/Attributes/Validation/Text.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - using System; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class Text : ValidationAttribute - { - private static readonly string[] ProhibitedWords = - { - "admin", "administrator", "root" - }; - - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - var reviewText = value.ToString()!; - - if (string.IsNullOrWhiteSpace(reviewText)) - { - return false; - } - - if (!Regex.IsMatch(reviewText, @"^[\p{L}\p{N}\s\p{P}]+$")) - { - return false; - } - - foreach (var word in ProhibitedWords) - { - if (reviewText.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) - { - return false; - } - } - - return true; - } - - - } - -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/TourAddress.cs b/TourService/Attributes/Validation/TourAddress.cs deleted file mode 100644 index 8fa2107..0000000 --- a/TourService/Attributes/Validation/TourAddress.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - public class TourAddress : ValidationAttribute - { - private static readonly string[] ProhibitedWords = - { - "admin", "administrator", "root" - }; - - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - var address = value.ToString()!; - - if (string.IsNullOrWhiteSpace(address)) - { - return false; - } - - var addressPattern = @"^\d+\s[A-Za-z0-9\s.,'-]+(?:\s(Apt|Suite|Unit|#)\s?\d+[A-Za-z]?)?,?\s?[A-Za-z\s]+(?:,\s?[A-Za-z]{2})?\s?\d{5}(-\d{4})?$"; - if (!Regex.IsMatch(address, addressPattern)) - { - return false; - } - - foreach (var word in ProhibitedWords) - { - if (address.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) - { - return false; - } - } - - - if (address.Length < 5) - { - return false; - } - - return true; - } - } -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/TourName.cs b/TourService/Attributes/Validation/TourName.cs deleted file mode 100644 index 953c23d..0000000 --- a/TourService/Attributes/Validation/TourName.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class TourName : ValidationAttribute - { - private static readonly string[] ProhibitedWords = { "admin", "administrator", "root" }; - - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - var benefitName = value.ToString()!; - - if (string.IsNullOrWhiteSpace(benefitName) || - !Regex.IsMatch(benefitName, @"^[a-zA-Z0-9\s\-]+$")) - { - return false; - } - - foreach (var word in ProhibitedWords) - { - if (benefitName.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) - { - return false; - } - } - - return true; - } - - } -} \ No newline at end of file diff --git a/TourService/Attributes/Validation/TourPrice.cs b/TourService/Attributes/Validation/TourPrice.cs deleted file mode 100644 index 5b674e2..0000000 --- a/TourService/Attributes/Validation/TourPrice.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Attributes.Validation -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - sealed public class TourPrice : ValidationAttribute - { - public override bool IsValid(object? value) - { - if (value == null) - { - return false; - } - - if (value is double price) - { - return price > 0; - } - - return false; - } - - } -} \ No newline at end of file diff --git a/TourService/Database/ApplicationContext.cs b/TourService/Database/ApplicationContext.cs deleted file mode 100644 index 9dd46b2..0000000 --- a/TourService/Database/ApplicationContext.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using TourService.Database.Models; - -namespace TourService.Database -{ - public class ApplicationContext : DbContext - { - public DbSet Benefits { get; set; } - public DbSet Categories { get; set; } - public DbSet Photos { get; set; } - public DbSet Reviews { get; set; } - public DbSet ReviewBenefits { get; set; } - public DbSet Tags { get; set; } - public DbSet Tours { get; set; } - public DbSet TourCategories { get; set; } - public DbSet TourWishes { get; set; } - public ApplicationContext(DbContextOptions options) : base(options) - { - Database.EnsureCreated(); - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - } - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Benefit.cs b/TourService/Database/Models/Benefit.cs deleted file mode 100644 index 669ab15..0000000 --- a/TourService/Database/Models/Benefit.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Benefit - { - [Key] - public long Id { get; set; } - [TourName] - public string Name { get; set; } = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Category.cs b/TourService/Database/Models/Category.cs deleted file mode 100644 index 2fbb4f5..0000000 --- a/TourService/Database/Models/Category.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Category - { - [Key] - public long Id { get; set; } - [TourName] - public string Name {get;set;} = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Photo.cs b/TourService/Database/Models/Photo.cs deleted file mode 100644 index 7f2115a..0000000 --- a/TourService/Database/Models/Photo.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Photo - { - [Key] - public long Id { get; set; } - [FileLink] - public string FileLink {get;set;} = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Review.cs b/TourService/Database/Models/Review.cs deleted file mode 100644 index d0b6e57..0000000 --- a/TourService/Database/Models/Review.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Review - { - [Key] - public long Id { get; set; } - [Required] - public long UserId { get; set; } - [Rating(1,10)] - public int Rating {get;set;} - [Text] - public string Text {get; set;} = null!; - [Required] - public bool IsAnonymous {get; set;} - [Required] - public bool Removed {get; set;} - } -} \ No newline at end of file diff --git a/TourService/Database/Models/ReviewBenefit.cs b/TourService/Database/Models/ReviewBenefit.cs deleted file mode 100644 index c54f1af..0000000 --- a/TourService/Database/Models/ReviewBenefit.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Database.Models -{ - public class ReviewBenefit - { - [Key] - public long Id { get; set; } - [ForeignKey("RewiewId")] - public long ReviewId { get; set; } - [Required] - public Review Review { get;set; } = null!; - [ForeignKey("BenefitId")] - public long BenefitId { get; set; } - [Required] - public Benefit Benefit { get; set; } = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Tag.cs b/TourService/Database/Models/Tag.cs deleted file mode 100644 index 0d749ac..0000000 --- a/TourService/Database/Models/Tag.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Tag - { - [Key] - public long Id { get; set; } - [TourName] - public string Name { get; set; } = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/Tour.cs b/TourService/Database/Models/Tour.cs deleted file mode 100644 index ab8ab04..0000000 --- a/TourService/Database/Models/Tour.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Attributes.Validation; - -namespace TourService.Database.Models -{ - public class Tour - { - [Key] - public long Id { get; set; } - [TourName] - public string Name { get; set; } = null!; - [TourService.Attributes.Validation.Description] - public string Description { get; set; } = null!; - [TourName] - public double Price {get; set; } - [TourAddress] - public string Address { get; set; } = null!; - [Coordinates] - public string Coordinates { get; set; } = null!; - [Required] - public double SettlementDistance {get; set; } - [Required] - public bool IsActive { get; set; } - [Text] - public string Comment { get; set;} = null!; - [Required] - public DateTime BeginDate { get; set; } - [Required] - public DateTime EndDate { get; set; } - public ICollection? Photos { get; set; } - public ICollection? Reviews { get; set; } - } -} \ No newline at end of file diff --git a/TourService/Database/Models/TourCategory.cs b/TourService/Database/Models/TourCategory.cs deleted file mode 100644 index f821fa4..0000000 --- a/TourService/Database/Models/TourCategory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Database.Models -{ - public class TourCategory - { - [Key] - public long Id { get; set; } - [ForeignKey("TourId")] - public long TourId { get; set; } - [Required] - public Tour Tour { get; set; } = null!; - [ForeignKey("CategoryId")] - public long CategoryId { get; set; } - [Required] - public Category Category{ get; set; } = null!; - } -} \ No newline at end of file diff --git a/TourService/Database/Models/TourWish.cs b/TourService/Database/Models/TourWish.cs deleted file mode 100644 index b8c2fb9..0000000 --- a/TourService/Database/Models/TourWish.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Database.Models -{ - public class TourWish - { - [Key] - public long Id { get; set; } - [Required] - public long UserId { get; set; } - [ForeignKey("TourId")] - public long TourId { get; set; } - [Required] - public Tour Tour { get; set; } = null!; - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/BucketNotFoundException.cs b/TourService/Exceptions/S3ServiceExceptions/BucketNotFoundException.cs deleted file mode 100644 index 39b67a5..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/BucketNotFoundException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - [System.Serializable] - public class BucketNotFoundException : System.Exception - { - public BucketNotFoundException() { } - public BucketNotFoundException(string message) : base(message) { } - public BucketNotFoundException(string message, System.Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/ConfigureBucketsException.cs b/TourService/Exceptions/S3ServiceExceptions/ConfigureBucketsException.cs deleted file mode 100644 index d7d63e2..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/ConfigureBucketsException.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - public class ConfigureBucketsException : System.Exception - { - public ConfigureBucketsException() {} - public ConfigureBucketsException(string message) : base(message) {} - public ConfigureBucketsException(string message, System.Exception inner) : base(message, inner) {} - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs b/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs deleted file mode 100644 index 2997a79..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/DeleteBucketException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - [System.Serializable] - public class DeleteBucketException : System.Exception - { - public DeleteBucketException() { } - public DeleteBucketException(string message) : base(message) { } - public DeleteBucketException(string message, System.Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/DeleteImageException.cs b/TourService/Exceptions/S3ServiceExceptions/DeleteImageException.cs deleted file mode 100644 index 4cbc10c..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/DeleteImageException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - [System.Serializable] - public class DeleteImageException : System.Exception - { - public DeleteImageException() { } - public DeleteImageException(string message) : base(message) { } - public DeleteImageException(string message, System.Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/GetImageException.cs b/TourService/Exceptions/S3ServiceExceptions/GetImageException.cs deleted file mode 100644 index 5458ea7..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/GetImageException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - [System.Serializable] - public class GetImageException : System.Exception - { - public GetImageException() { } - public GetImageException(string message) : base(message) { } - public GetImageException(string message, System.Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/ImageNotFoundException.cs b/TourService/Exceptions/S3ServiceExceptions/ImageNotFoundException.cs deleted file mode 100644 index 2e83021..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/ImageNotFoundException.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - public class ImageNotFoundException : System.Exception - { - public ImageNotFoundException() {} - public ImageNotFoundException(string message) : base(message) {} - public ImageNotFoundException(string message, System.Exception inner) : base(message, inner) {} - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs b/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs deleted file mode 100644 index 9bd7995..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/StorageUnavailibleException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - [System.Serializable] - public class StorageUnavailibleException : System.Exception - { - public StorageUnavailibleException() { } - public StorageUnavailibleException(string message) : base(message) { } - public StorageUnavailibleException(string message, System.Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/TourService/Exceptions/S3ServiceExceptions/UploadImageException.cs b/TourService/Exceptions/S3ServiceExceptions/UploadImageException.cs deleted file mode 100644 index b2e074e..0000000 --- a/TourService/Exceptions/S3ServiceExceptions/UploadImageException.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace TourService.Exceptions.S3ServiceExceptions -{ - public class UploadImageException : System.Exception - { - public UploadImageException() {} - public UploadImageException(string message) : base(message) {} - public UploadImageException(string message, System.Exception inner) : base(message, inner) {} - } -} \ No newline at end of file diff --git a/TourService/Kafka/KafkaRequestService.cs b/TourService/Kafka/KafkaRequestService.cs deleted file mode 100644 index 3b64d39..0000000 --- a/TourService/Kafka/KafkaRequestService.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Confluent.Kafka; -using TourService.Kafka; -using TourService.KafkaException; -using TourService.KafkaException.ConsumerException; -using TourService.Kafka.Utils; -using TourService.KafkaException.ConfigurationException; - -namespace TourService.Kafka -{ - public class KafkaRequestService - { - private readonly IProducer _producer; - private readonly ILogger _logger; - private readonly KafkaTopicManager _kafkaTopicManager; - private readonly HashSet _pendingMessagesBus; - private readonly HashSet _recievedMessagesBus; - private readonly HashSet> _consumerPool; - public KafkaRequestService( - IProducer producer, - ILogger logger, - KafkaTopicManager kafkaTopicManager, - List responseTopics, - List requestsTopics) - { - _producer = producer; - _logger = logger; - _kafkaTopicManager = kafkaTopicManager; - _recievedMessagesBus = ConfigureRecievedMessages(responseTopics); - _pendingMessagesBus = ConfigurePendingMessages(requestsTopics); - _consumerPool = ConfigureConsumers(responseTopics.Count()); - - } - public void BeginRecieving(List responseTopics) - { - int topicCount = 0; - foreach(var consumer in _consumerPool) - { - - Thread thread = new Thread(async x=>{ - await Consume(consumer,responseTopics[topicCount]); - }); - thread.Start(); - topicCount++; - } - } - - private HashSet> ConfigureConsumers(int amount) - { - try - { - if(amount<=0) - { - throw new ConfigureConsumersException(" Amount of consumers must be above 0!"); - } - HashSet> consumers = new HashSet>(); - for (int i = 0; i < amount; i++) - { - consumers.Add( - new ConsumerBuilder( - new ConsumerConfig() - { - BootstrapServers = Environment.GetEnvironmentVariable("KAFKA_BROKERS"), - GroupId = "gatewayConsumer"+Guid.NewGuid().ToString(), - EnableAutoCommit = true, - AutoCommitIntervalMs = 10, - EnableAutoOffsetStore = true, - AutoOffsetReset = AutoOffsetReset.Earliest - - } - ).Build() - ); - } - return consumers; - } - catch (Exception ex) - { - if (ex is MyKafkaException) - { - _logger.LogError(ex, "Error configuring consumers"); - throw new ProducerException("Error configuring consumers",ex); - } - throw; - } - - } - private HashSet ConfigurePendingMessages(List ResponseTopics) - { - if(ResponseTopics.Count == 0) - { - throw new ConfigureMessageBusException("At least one requests topic must e provided!"); - } - var PendingMessages = new HashSet(); - foreach(var requestTopic in ResponseTopics) - { - PendingMessages.Add(new PendingMessagesBus(){ TopicName=requestTopic, MessageKeys = new HashSet()}); - } - return PendingMessages; - } - private HashSet ConfigureRecievedMessages(List ResponseTopics) - { - if(ResponseTopics.Count == 0) - { - throw new ConfigureMessageBusException("At least one response topic must e provided!"); - } - HashSet Responses = new HashSet(); - foreach(var RequestTopic in ResponseTopics) - { - Responses.Add(new RecievedMessagesBus() { TopicName = RequestTopic, Messages = new HashSet>()}); - } - return Responses; - } - - private bool IsTopicAvailable(string topicName) - { - try - { - _logger.LogError("Unable to subscribe to topic"); - throw new ConsumerTopicUnavailableException("Topic unavailable"); - - } - catch (Exception e) - { - if (e is MyKafkaException) - { - _logger.LogError(e,"Error checking topic"); - throw new ConsumerException("Error checking topic",e); - } - _logger.LogError(e,"Unhandled error"); - throw; - } - } - - public bool IsMessageRecieved(string MessageKey) - { - try - { - return _recievedMessagesBus.Any(x=>x.Messages.Any(x=>x.Key==MessageKey)); - } - catch (Exception e) - { - throw new ConsumerException($"Recieved message bus error",e); - } - } - public async Task Produce(string topicName, Message message, string responseTopic) - { - try - { - bool IsTopicExists = IsTopicAvailable(topicName); - if (IsTopicExists && IsTopicPendingMessageBusExist( responseTopic)) - { - var deliveryResult = await _producer.ProduceAsync(topicName, message); - if (deliveryResult.Status == PersistenceStatus.Persisted) - { - _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); - - _pendingMessagesBus.FirstOrDefault(x=>x.TopicName == responseTopic).MessageKeys.Add(new MethodKeyPair(){ - MessageKey = message.Key, - MessageMethod = Encoding.UTF8.GetString(message.Headers.FirstOrDefault(x => x.Key.Equals("method")).GetValueBytes()) - }); - return true; - - - } - - _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); - throw new MessageProduceException("Message delivery status: Not persisted" + deliveryResult.Value); - - } - - bool IsTopicCreated = _kafkaTopicManager.CreateTopic(topicName, Convert.ToInt32(Environment.GetEnvironmentVariable("PARTITIONS_STANDART")), Convert.ToInt16(Environment.GetEnvironmentVariable("REPLICATION_FACTOR_STANDART"))); - if (IsTopicCreated && IsTopicPendingMessageBusExist( responseTopic)) - { - var deliveryResult = await _producer.ProduceAsync(topicName, message); - if (deliveryResult.Status == PersistenceStatus.Persisted) - { - _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); - _pendingMessagesBus.FirstOrDefault(x=>x.TopicName == responseTopic).MessageKeys.Add(new MethodKeyPair(){ - MessageKey = message.Key, - MessageMethod = Encoding.UTF8.GetString(message.Headers.FirstOrDefault(x => x.Key.Equals("method")).GetValueBytes()) - }); - return true; - } - - _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); - throw new MessageProduceException("Message delivery status: Not persisted"); - - } - _logger.LogError("Topic unavailable"); - throw new MessageProduceException("Topic unavailable"); - } - catch (Exception e) - { - if (e is MyKafkaException) - { - _logger.LogError(e, "Error producing message"); - throw new ProducerException("Error producing message",e); - } - throw; - } - } - private bool IsTopicPendingMessageBusExist(string responseTopic) - { - return _pendingMessagesBus.Any(x => x.TopicName == responseTopic); - } - private async Task Consume(IConsumer localConsumer,string topicName) - { - localConsumer.Subscribe(topicName); - while (true) - { - ConsumeResult result = localConsumer.Consume(); - - if (result != null) - { - try - { - if( _pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName).MessageKeys.Any(x=>x.MessageKey==result.Message.Key)) - { - if(result.Message.Headers.Any(x => x.Key.Equals("errors"))) - { - var errors = Encoding.UTF8.GetString(result.Message.Headers.FirstOrDefault(x => x.Key.Equals("errors")).GetValueBytes()); - _logger.LogError(errors); - - throw new ConsumerException(errors); - } - - MethodKeyPair pendingMessage = _pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName).MessageKeys.FirstOrDefault(x=>x.MessageKey==result.Message.Key); - if(_pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName).MessageKeys.Any(x=>x.MessageMethod== Encoding.UTF8.GetString(result.Message.Headers.FirstOrDefault(x => x.Key.Equals("method")).GetValueBytes()))) - { - - localConsumer.Commit(result); - _recievedMessagesBus.FirstOrDefault(x=>x.TopicName== topicName).Messages.Add(result.Message); - _pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName).MessageKeys.Remove(pendingMessage); - } - _logger.LogError("Wrong message method"); - throw new ConsumerException("Wrong message method"); - } - } - catch (Exception e) - { - if (e is MyKafkaException) - { - _logger.LogError(e,"Consumer error"); - throw new ConsumerException("Consumer error ",e); - } - _logger.LogError(e,"Unhandled error"); - localConsumer.Commit(result); - throw; - } - - } - } - } - } -} \ No newline at end of file diff --git a/TourService/Kafka/KafkaService.cs b/TourService/Kafka/KafkaService.cs deleted file mode 100644 index 6d11c9a..0000000 --- a/TourService/Kafka/KafkaService.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System.ComponentModel; -using System.Text; -using Confluent.Kafka; -using TourService.KafkaException; -using TourService.KafkaException.ConsumerException; -using Newtonsoft.Json; -namespace TourService.Kafka; - -public abstract class KafkaService(ILogger logger, IProducer producer, KafkaTopicManager kafkaTopicManager) -{ - protected readonly IProducer _producer = producer; - protected readonly ILogger _logger = logger; - protected readonly KafkaTopicManager _kafkaTopicManager = kafkaTopicManager; - protected IConsumer?_consumer; - - protected void ConfigureConsumer(string topicName) - { - try - { - var config = new ConsumerConfig - { - GroupId = "test-consumer-group", - BootstrapServers = Environment.GetEnvironmentVariable("BOOTSTRAP_SERVERS"), - AutoOffsetReset = AutoOffsetReset.Earliest - }; - _consumer = new ConsumerBuilder(config).Build(); - if(IsTopicAvailable(topicName)) - { - _consumer.Subscribe(topicName); - } - throw new ConsumerTopicUnavailableException("Topic unavailable"); - } - catch (Exception e) - { - if (e is MyKafkaException) - { - _logger.LogError(e,"Error configuring consumer"); - throw new ConsumerException("Error configuring consumer",e); - } - _logger.LogError(e,"Unhandled error"); - throw; - } - } - private bool IsTopicAvailable(string topicName) - { - try - { - bool IsTopicExists = _kafkaTopicManager.CheckTopicExists(topicName); - if (IsTopicExists) - { - return IsTopicExists; - } - _logger.LogError("Unable to subscribe to topic"); - throw new ConsumerTopicUnavailableException("Topic unavailable"); - - } - catch (Exception e) - { - if (e is MyKafkaException) - { - _logger.LogError(e,"Error checking topic"); - throw new ConsumerException("Error checking topic",e); - } - _logger.LogError(e,"Unhandled error"); - throw; - } - } - public abstract Task Consume(); - public async Task Produce( string topicName,Message message) - { - try - { - bool IsTopicExists = IsTopicAvailable(topicName); - if (IsTopicExists) - { - var deliveryResult = await _producer.ProduceAsync(topicName, message); - if (deliveryResult.Status == PersistenceStatus.Persisted) - { - - _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); - return true; - } - - _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); - throw new MessageProduceException("Message delivery status: Not persisted" + deliveryResult.Value); - - } - - bool IsTopicCreated = _kafkaTopicManager.CreateTopic(topicName, Convert.ToInt32(Environment.GetEnvironmentVariable("PARTITIONS_STANDART")), Convert.ToInt16(Environment.GetEnvironmentVariable("REPLICATION_FACTOR_STANDART"))); - if (IsTopicCreated) - { - var deliveryResult = await _producer.ProduceAsync(topicName, message); - if (deliveryResult.Status == PersistenceStatus.Persisted) - { - _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); - return true; - } - - _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); - throw new MessageProduceException("Message delivery status: Not persisted"); - - } - _logger.LogError("Topic unavailable"); - throw new MessageProduceException("Topic unavailable"); - } - catch (Exception e) - { - if (e is MyKafkaException) - { - _logger.LogError(e, "Error producing message"); - throw new ProducerException("Error producing message",e); - } - throw; - } - - - - } - - -} \ No newline at end of file diff --git a/TourService/Kafka/KafkaTopicManager.cs b/TourService/Kafka/KafkaTopicManager.cs deleted file mode 100644 index 9825681..0000000 --- a/TourService/Kafka/KafkaTopicManager.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Confluent.Kafka; -using Confluent.Kafka.Admin; -using TourService.KafkaException; - -namespace TourService.Kafka; - -public class KafkaTopicManager(IAdminClient adminClient) -{ - private readonly IAdminClient _adminClient = adminClient; - - /// - /// Checks if a Kafka topic with the specified name exists. - /// - /// The name of the topic to check. - /// True if the topic exists, false otherwise. - /// Thrown if the topic check fails. - public bool CheckTopicExists(string topicName) - { - try - { - var topicExists = _adminClient.GetMetadata(topicName, TimeSpan.FromSeconds(10)); - if (topicExists.Topics.Count == 0) - { - return false; - } - return true; - } - catch (Exception e) - { - - Console.WriteLine($"An error occurred: {e.Message}"); - throw new CheckTopicException("Failed to check topic"); - } - } - - /// - /// Creates a new Kafka topic with the specified name, number of partitions, and replication factor. - /// - /// The name of the topic to create. - /// The number of partitions for the topic. - /// The replication factor for the topic. - /// True if the topic was successfully created, false otherwise. - /// Thrown if the topic creation fails. - public bool CreateTopic(string topicName, int numPartitions, short replicationFactor) - { - try - { - - var result = _adminClient.CreateTopicsAsync(new TopicSpecification[] - { - new() { - Name = topicName, - NumPartitions = numPartitions, - ReplicationFactor = replicationFactor, - Configs = new Dictionary - { - { "min.insync.replicas", "2" } - }} - }); - if (result.IsCompleted) - { - return true; - } - throw new CreateTopicException("Failed to create topic"); - } - catch (Exception e) - { - Console.WriteLine(e); - throw new CreateTopicException("Failed to create topic"); - } - } - - -} \ No newline at end of file diff --git a/TourService/Kafka/Utils/MethodKeyPair.cs b/TourService/Kafka/Utils/MethodKeyPair.cs deleted file mode 100644 index f022f61..0000000 --- a/TourService/Kafka/Utils/MethodKeyPair.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Kafka.Utils -{ - public class MethodKeyPair - { - public string MessageKey { get; set; } = ""; - public string MessageMethod {get;set;} = ""; - } -} \ No newline at end of file diff --git a/TourService/Kafka/Utils/PendingMessagesBus.cs b/TourService/Kafka/Utils/PendingMessagesBus.cs deleted file mode 100644 index 6602342..0000000 --- a/TourService/Kafka/Utils/PendingMessagesBus.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using TourService.Kafka.Utils; - -namespace TourService.Kafka -{ - public class PendingMessagesBus - { - public string TopicName {get;set;} = ""; - public HashSet MessageKeys {get;set;} = new HashSet(); - } -} \ No newline at end of file diff --git a/TourService/Kafka/Utils/RecievedMessagesBus.cs b/TourService/Kafka/Utils/RecievedMessagesBus.cs deleted file mode 100644 index 8db6b95..0000000 --- a/TourService/Kafka/Utils/RecievedMessagesBus.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Confluent.Kafka; - -namespace TourService.Kafka -{ - public class RecievedMessagesBus - { - public string TopicName { get; set; } = ""; - public HashSet> Messages { get; set;} = new HashSet>(); - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ConfigurationException/ConfigureConsumersException.cs b/TourService/KafkaException/ConfigurationException/ConfigureConsumersException.cs deleted file mode 100644 index 911b2fd..0000000 --- a/TourService/KafkaException/ConfigurationException/ConfigureConsumersException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using TourService.KafkaException; - -namespace TourService.KafkaException.ConfigurationException -{ - public class ConfigureConsumersException : MyKafkaException - { - public ConfigureConsumersException() {} - public ConfigureConsumersException(string message) : base(message) {} - public ConfigureConsumersException(string message, System.Exception inner) : base(message, inner) {} - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs b/TourService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs deleted file mode 100644 index d2db883..0000000 --- a/TourService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using TourService.KafkaException; - -namespace TourService.KafkaException.ConfigurationException -{ - public class ConfigureMessageBusException : MyKafkaException - { - public ConfigureMessageBusException() {} - public ConfigureMessageBusException(string message) : base(message) {} - public ConfigureMessageBusException(string message, System.Exception inner) : base(message, inner) {} - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ConsumerException/ConsumerException.cs b/TourService/KafkaException/ConsumerException/ConsumerException.cs deleted file mode 100644 index 06a63ee..0000000 --- a/TourService/KafkaException/ConsumerException/ConsumerException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException.ConsumerException; - -public class ConsumerException : MyKafkaException -{ - public ConsumerException() - { - } - - public ConsumerException(string message) - : base(message) - { - } - - public ConsumerException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs b/TourService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs deleted file mode 100644 index 416c5ff..0000000 --- a/TourService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException.ConsumerException; - -public class ConsumerRecievedMessageInvalidException : ConsumerException -{ - public ConsumerRecievedMessageInvalidException() - { - } - - public ConsumerRecievedMessageInvalidException(string message) - : base(message) - { - } - - public ConsumerRecievedMessageInvalidException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs b/TourService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs deleted file mode 100644 index 46835d7..0000000 --- a/TourService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException.ConsumerException; - -public class ConsumerTopicUnavailableException : ConsumerException -{ - public ConsumerTopicUnavailableException() - { - } - - public ConsumerTopicUnavailableException(string message) - : base(message) - { - } - - public ConsumerTopicUnavailableException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/KafkaException/MyKafkaException.cs b/TourService/KafkaException/MyKafkaException.cs deleted file mode 100644 index 4ca7eed..0000000 --- a/TourService/KafkaException/MyKafkaException.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace TourService.KafkaException; - -public class MyKafkaException : Exception -{ - public MyKafkaException() - { - - } - - public MyKafkaException(string message) - : base(message) - { - - } - - public MyKafkaException(string message, Exception innerException) - : base(message, innerException) - { - - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ProducerExceptions/MessageProduceException.cs b/TourService/KafkaException/ProducerExceptions/MessageProduceException.cs deleted file mode 100644 index e1b833f..0000000 --- a/TourService/KafkaException/ProducerExceptions/MessageProduceException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException; - -public class MessageProduceException : ProducerException -{ - public MessageProduceException() - { - } - - public MessageProduceException(string message) - : base(message) - { - } - - public MessageProduceException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/KafkaException/ProducerExceptions/ProducerException.cs b/TourService/KafkaException/ProducerExceptions/ProducerException.cs deleted file mode 100644 index 8e4a6f8..0000000 --- a/TourService/KafkaException/ProducerExceptions/ProducerException.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace TourService.KafkaException; - -public class ProducerException : MyKafkaException -{ - public ProducerException() - { - - } - - public ProducerException(string message) - : base(message) - { - - } - - public ProducerException(string message, Exception innerException) - : base(message, innerException) - { - - } -} \ No newline at end of file diff --git a/TourService/KafkaException/TopicExceptions/CheckTopicException.cs b/TourService/KafkaException/TopicExceptions/CheckTopicException.cs deleted file mode 100644 index 63d6546..0000000 --- a/TourService/KafkaException/TopicExceptions/CheckTopicException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException; - -public class CheckTopicException : TopicException -{ - public CheckTopicException() - { - } - - public CheckTopicException(string message) - : base(message) - { - } - - public CheckTopicException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/KafkaException/TopicExceptions/CreateTopicException.cs b/TourService/KafkaException/TopicExceptions/CreateTopicException.cs deleted file mode 100644 index 22053ba..0000000 --- a/TourService/KafkaException/TopicExceptions/CreateTopicException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException; - -public class CreateTopicException : TopicException -{ - public CreateTopicException() - { - } - - public CreateTopicException(string message) - : base(message) - { - } - - public CreateTopicException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/KafkaException/TopicExceptions/TopicException.cs b/TourService/KafkaException/TopicExceptions/TopicException.cs deleted file mode 100644 index 3c52c6a..0000000 --- a/TourService/KafkaException/TopicExceptions/TopicException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace TourService.KafkaException; - -public class TopicException : MyKafkaException -{ - public TopicException() - { - } - - public TopicException(string message) - : base(message) - { - } - - public TopicException(string message, Exception innerException) - : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/TourService/Models/Tours/Responses/GetToursResponse.cs b/TourService/Models/Tours/Responses/GetToursResponse.cs deleted file mode 100644 index d09e42f..0000000 --- a/TourService/Models/Tours/Responses/GetToursResponse.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using TourService.Database.Models; - -namespace TourService.Models.Tours.Responses -{ - public class GetToursResponse - { - - } -} \ No newline at end of file diff --git a/TourService/Program.cs b/TourService/Program.cs deleted file mode 100644 index 1760df1..0000000 --- a/TourService/Program.cs +++ /dev/null @@ -1,6 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); -var app = builder.Build(); - -app.MapGet("/", () => "Hello World!"); - -app.Run(); diff --git a/TourService/Properties/launchSettings.json b/TourService/Properties/launchSettings.json deleted file mode 100644 index 948032e..0000000 --- a/TourService/Properties/launchSettings.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:53249", - "sslPort": 44303 - } - }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5151", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "https://localhost:7210;http://localhost:5151", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/TourService/Repository/FindOptions.cs b/TourService/Repository/FindOptions.cs deleted file mode 100644 index 42ce7b4..0000000 --- a/TourService/Repository/FindOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace TourService.Repository -{ - public class FindOptions - { - public bool IsIgnoreAutoIncludes { get; set; } - public bool IsAsNoTracking { get; set; } - } -} \ No newline at end of file diff --git a/TourService/Repository/IRepository.cs b/TourService/Repository/IRepository.cs deleted file mode 100644 index e70e6ac..0000000 --- a/TourService/Repository/IRepository.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Linq.Expressions; - -namespace TourService.Repository -{ - public interface IRepository where TEntity : class - { - IQueryable GetAll(FindOptions? findOptions = null); - Task FindOneAsync(Expression> predicate, FindOptions? findOptions = null); - IQueryable Find(Expression> predicate, FindOptions? findOptions = null); - Task AddAsync(TEntity entity); - Task AddManyAsync(IEnumerable entities); - bool Update(TEntity entity); - bool Delete(TEntity entity); - bool DeleteMany(Expression> predicate); - Task AnyAsync(Expression> predicate); - Task CountAsync(Expression> predicate); - } -} \ No newline at end of file diff --git a/TourService/Repository/Repository.cs b/TourService/Repository/Repository.cs deleted file mode 100644 index ffb2039..0000000 --- a/TourService/Repository/Repository.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Linq.Expressions; -using TourService.Database; -using Microsoft.EntityFrameworkCore; - -namespace TourService.Repository -{ - public class Repository : IRepository where TEntity : class - { - private readonly ApplicationContext _empDBContext; - public Repository(ApplicationContext empDBContext) - { - _empDBContext = empDBContext; - } - public async Task AddAsync(TEntity entity) - { - await _empDBContext.Set().AddAsync(entity); - return await _empDBContext.SaveChangesAsync()>= 0; - } - public async Task AddManyAsync(IEnumerable entities) - { - await _empDBContext.Set().AddRangeAsync(entities); - return await _empDBContext.SaveChangesAsync()>= 0; - } - public bool Delete(TEntity entity) - { - _empDBContext.Set().Remove(entity); - return _empDBContext.SaveChanges()>= 0; - } - public bool DeleteMany(Expression> predicate) - { - var entities = Find(predicate); - _empDBContext.Set().RemoveRange(entities); - return _empDBContext.SaveChanges()>= 0; - } - public async Task FindOneAsync(Expression> predicate, FindOptions? findOptions = null) - { - return await Get(findOptions).FirstOrDefaultAsync(predicate)! ?? throw new NullReferenceException("Entity not found!"); - } - public IQueryable Find(Expression> predicate, FindOptions? findOptions = null) - { - return Get(findOptions).Where(predicate); - } - public IQueryable GetAll(FindOptions? findOptions = null) - { - return Get(findOptions); - } - public bool Update(TEntity entity) - { - _empDBContext.Set().Update(entity); - return _empDBContext.SaveChanges()>= 0; - } - public async Task AnyAsync(Expression> predicate) - { - return await _empDBContext.Set().AnyAsync(predicate); - } - public async Task CountAsync(Expression> predicate) - { - return await _empDBContext.Set().CountAsync(predicate); - } - private DbSet Get(FindOptions? findOptions = null) - { - findOptions ??= new FindOptions(); - var entity = _empDBContext.Set(); - if (findOptions.IsAsNoTracking && findOptions.IsIgnoreAutoIncludes) - { - entity.IgnoreAutoIncludes().AsNoTracking(); - } - else if (findOptions.IsIgnoreAutoIncludes) - { - entity.IgnoreAutoIncludes(); - } - else if (findOptions.IsAsNoTracking) - { - entity.AsNoTracking(); - } - return entity; - } - } -} \ No newline at end of file diff --git a/TourService/Services/S3/IS3Service.cs b/TourService/Services/S3/IS3Service.cs deleted file mode 100644 index cb8487d..0000000 --- a/TourService/Services/S3/IS3Service.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using TourService.Database.Models; - -namespace TourService.Services.S3 -{ - public interface IS3Service - { - //FIXME: Fix responses - Task ConfigureBuckets(); - Task UploadImageToS3Bucket(byte[] imageBytes, string template, string imageName); - Task DeleteImageFromS3Bucket(string fileName, string bucketName); - Task GetImageFromS3Bucket(string fileName, string bucketName); - Task CheckIfBucketExists(string bucketName); - Task DeleteBucket(string bucketName); - Task CreateBucket(string bucketName); - } -} \ No newline at end of file diff --git a/TourService/Services/S3/S3Service.cs b/TourService/Services/S3/S3Service.cs deleted file mode 100644 index 33339d3..0000000 --- a/TourService/Services/S3/S3Service.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Amazon.S3; -using Amazon.S3.Model; -using Amazon.S3.Util; -using TourService.Database.Models; -using TourService.Exceptions.S3ServiceExceptions; -using TourService.Utils.Models; - -namespace TourService.Services.S3 -{ - public class S3Service : IS3Service - { - private readonly IAmazonS3 _s3Client; - private readonly ILogger _logger; - private readonly IConfiguration _configuration; - public S3Service(IAmazonS3 s3Client, ILogger logger, IConfiguration configuration) - { - _s3Client = s3Client; - _logger = logger; - _configuration = configuration; - } - public async Task ConfigureBuckets() - { - try - { - - List buckets = _configuration.GetSection("Buckets").Get>() ?? throw new NullReferenceException(); - foreach (var bucket in buckets) - { - - if(!await AmazonS3Util.DoesS3BucketExistV2Async(_s3Client,bucket.BucketId.ToString())) - { - await _s3Client.PutBucketAsync(bucket.BucketId.ToString()); - } - } - - foreach(var bucket in buckets) - { - if(!await CheckIfBucketExists(bucket.BucketId.ToString())) - { - _logger.LogError("Failed to configure S3 buckets, storage unavailable!"); - throw new StorageUnavailibleException("Failed to configure S3 buckets, storage unavailable!"); - } - } - _logger.LogInformation("S3 buckets configured!"); - } - catch (Exception ex) - { - - _logger.LogError(ex, "Failed to configure S3 buckets!"); - throw new ConfigureBucketsException("Failed to configure S3 buckets!", ex); - } - } - public async Task CreateBucket(string bucketName) - { - try - { - if(!await AmazonS3Util.DoesS3BucketExistV2Async(_s3Client,bucketName)) - { - await _s3Client.PutBucketAsync(bucketName); - return true; - } - _logger.LogInformation($"Bucket {bucketName} already exists!"); - throw new BucketAlreadyExistsException($"Bucket {bucketName} already exists!"); - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to create bucket!"); - throw new ConfigureBucketsException("Failed to create bucket!", ex); - } - } - - public async Task CheckIfBucketExists(string bucketName) - { - return await AmazonS3Util.DoesS3BucketExistV2Async(_s3Client, bucketName); - } - public async Task DeleteBucket(string bucketName) - { - try - { - DeleteBucketResponse response = await _s3Client.DeleteBucketAsync(bucketName); - _logger.LogInformation(response.HttpStatusCode.ToString()+ response.ResponseMetadata.ToString()); - if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) - { - _logger.LogInformation($"Bucket {bucketName} deleted!"); - return true; - } - if (response.HttpStatusCode == System.Net.HttpStatusCode.NotFound) - { - _logger.LogError($"Bucket {bucketName} not found!"); - throw new BucketNotFoundException($"Bucket {bucketName} not found!"); - } - if (response.HttpStatusCode == System.Net.HttpStatusCode.InternalServerError) - { - _logger.LogError($"Failed to delete bucket {bucketName}!"); - throw new DeleteBucketException($"Failed to delete bucket {bucketName}!"); - } - _logger.LogError($"Failed to delete bucket {bucketName}, unhandled exception!"); - throw new DeleteBucketException($"Failed to delete bucket {bucketName}, unhandled exception!"); - } - catch (Exception ex) - { - _logger.LogError(ex, $"Failed to delete bucket {bucketName}!"); - throw new DeleteBucketException($"Failed to delete bucket {bucketName}!", ex); - } - } - public async Task DeleteImageFromS3Bucket(string fileName, string bucketName) - { - try - { - DeleteObjectResponse response = await _s3Client.DeleteObjectAsync(bucketName, fileName); - if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) - { - _logger.LogInformation($"Image {fileName} deleted from S3 bucket {bucketName}!"); - return true; - } - if (response.HttpStatusCode == System.Net.HttpStatusCode.NotFound) - { - _logger.LogError($"Image {fileName} not found in S3 bucket {bucketName}!"); - throw new ImageNotFoundException($"Image {fileName} not found in S3 bucket {bucketName}!"); - } - if (response.HttpStatusCode == System.Net.HttpStatusCode.InternalServerError) - { - _logger.LogError($"Failed to delete image {fileName} from S3 bucket {bucketName}, storage unavailible!"); - throw new DeleteImageException($"Failed to delete image {fileName} from S3 bucket {bucketName}, storage unavailible!"); - } - _logger.LogError($"Failed to delete image {fileName} from S3 bucket {bucketName}, unhandled exception!" + response.ToString()); - throw new DeleteImageException($"Failed to delete image {fileName} from S3 bucket {bucketName}!, unhandled exception!" + response.ToString()); - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to delete image from S3 bucket!"); - throw new DeleteImageException("Failed to delete image from S3 bucket!", ex); - } - } - - public async Task GetImageFromS3Bucket(string fileName, string bucketName) - { - try - { - GetObjectMetadataResponse metadataResponse = await _s3Client.GetObjectMetadataAsync(bucketName, fileName); - if(metadataResponse.HttpStatusCode == System.Net.HttpStatusCode.OK) - { - var response = _s3Client.GetPreSignedURL(new GetPreSignedUrlRequest(){ BucketName = bucketName, Key = fileName, Expires = DateTime.Now.AddYears(10), Protocol = Protocol.HTTP}); - _logger.LogInformation($"Uri for image {fileName} aquired from S3 bucket {bucketName}!"); - return new Photo() - { - FileLink = response - - }; - } - if(metadataResponse.HttpStatusCode == System.Net.HttpStatusCode.NotFound) - { - _logger.LogError($"Image {fileName} not found in S3 bucket {bucketName}!"); - throw new ImageNotFoundException($"Image {fileName} not found in S3 bucket {bucketName}!"); - } - if(metadataResponse.HttpStatusCode == System.Net.HttpStatusCode.InternalServerError) - { - _logger.LogError($"Failed to get image {fileName} from S3 bucket {bucketName}, storage unavailible!"); - throw new GetImageException($"Failed to get image {fileName} from S3 bucket {bucketName}, storage unavailible!"); - } - _logger.LogError($"Failed to get image {fileName} from S3 bucket {bucketName}, unhandled exception!" + metadataResponse.ToString()); - throw new GetImageException($"Failed to get image {fileName} from S3 bucket {bucketName}!, unhandled exception!" + metadataResponse.ToString()); - - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to get image from S3 bucket!"); - throw new GetImageException("Failed to get image from S3 bucket!", ex); - } - } - public async Task UploadImageToS3Bucket(byte[] imageBytes, string template, string imageName) - { - try - { - PutObjectResponse response = await _s3Client.PutObjectAsync(new PutObjectRequest - { - BucketName = template, - Key = imageName, - InputStream = new MemoryStream(imageBytes), - ContentType = "image/png" - }); - if(response.HttpStatusCode == System.Net.HttpStatusCode.OK) - { - _logger.LogInformation($"Image {imageName} uploaded to S3 bucket {template}!"); - return true; - } - if(response.HttpStatusCode == System.Net.HttpStatusCode.InternalServerError) - { - _logger.LogError($"Failed to upload image {imageName} to S3 bucket {template}, storage unavailable!"); - throw new StorageUnavailibleException("Failed to upload image to S3 bucket, storage unavailable!"); - } - _logger.LogError($"Failed to upload image {imageName} to S3 bucket {template}, unhandled exception!" + response.ToString()); - throw new UploadImageException($"Failed to upload image {imageName} to S3 bucket {template}, unhandled exception!" + response.ToString()); - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to upload image to S3 bucket!"); - throw new UploadImageException("Failed to upload image to S3 bucket!", ex); - } - } - } -} \ No newline at end of file diff --git a/TourService/TourService.csproj b/TourService/TourService.csproj deleted file mode 100644 index 042b130..0000000 --- a/TourService/TourService.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TourService/TourService.sln b/TourService/TourService.sln deleted file mode 100644 index 0a43273..0000000 --- a/TourService/TourService.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.002.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TourService", "TourService.csproj", "{785D62E2-3117-44F3-BF1E-C2268B6F0639}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {785D62E2-3117-44F3-BF1E-C2268B6F0639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {785D62E2-3117-44F3-BF1E-C2268B6F0639}.Debug|Any CPU.Build.0 = Debug|Any CPU - {785D62E2-3117-44F3-BF1E-C2268B6F0639}.Release|Any CPU.ActiveCfg = Release|Any CPU - {785D62E2-3117-44F3-BF1E-C2268B6F0639}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CFB8621E-DA5C-4F24-9C25-FE0A61C684B8} - EndGlobalSection -EndGlobal diff --git a/TourService/Utils/Logging.cs b/TourService/Utils/Logging.cs deleted file mode 100644 index 331a30c..0000000 --- a/TourService/Utils/Logging.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Serilog; -using Serilog.Exceptions; -using Serilog.Sinks.OpenSearch; - -namespace TourService.Utils -{ - - public static class Logging - { - static OpenSearchSinkOptions _configureOpenSearchSink(IConfiguration configuration,string environment){ - return new OpenSearchSinkOptions(new Uri(configuration["OpenSearchConfiguration:Uri"]!)) - { - AutoRegisterTemplate = true, - IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name!.ToLower().Replace(".","-")}-{environment.ToLower()}-{DateTime.UtcNow:yyyy-MM-DD}", - NumberOfReplicas =1, - NumberOfShards = 1 - }; - } - - public static void configureLogging(){ - var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"; - var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings.json",optional:false,reloadOnChange:true).Build(); - Log.Logger = new LoggerConfiguration() - .Enrich.FromLogContext() - .Enrich.WithExceptionDetails() - .WriteTo.Debug() - .WriteTo.Console() - .WriteTo.OpenSearch(_configureOpenSearchSink(configuration,environment)) - .Enrich.WithProperty("Environment",environment) - .ReadFrom.Configuration(configuration) - .CreateLogger(); - } - } -} \ No newline at end of file diff --git a/TourService/Utils/Models/Bucket.cs b/TourService/Utils/Models/Bucket.cs deleted file mode 100644 index 37f6338..0000000 --- a/TourService/Utils/Models/Bucket.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace TourService.Utils.Models -{ - public class Bucket - { - public string BucketName { get; set; } = null!; - public Guid BucketId { get; set;} - } -} \ No newline at end of file diff --git a/TourService/appsettings.Development.json b/TourService/appsettings.Development.json deleted file mode 100644 index 578f901..0000000 --- a/TourService/appsettings.Development.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "Buckets":[ - { "BucketName": "TourImages", "BucketId": "d3b3c1e0-1c2e-4f3b-8c1e-1b2c3d4e5f6g" } - ] -} diff --git a/TourService/appsettings.json b/TourService/appsettings.json deleted file mode 100644 index 77167f0..0000000 --- a/TourService/appsettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" - -} From 66f0ec12aa7aae31c7b8a1618492379168f503a8 Mon Sep 17 00:00:00 2001 From: ereshkigal Date: Sat, 2 Nov 2024 23:58:56 +0300 Subject: [PATCH 3/7] Added logging and work with kafka --- OpenApiService/Kafka/KafkaRequestService.cs | 258 ++++++++++++++++++ OpenApiService/Kafka/KafkaService.cs | 121 ++++++++ OpenApiService/Kafka/KafkaTopicManager.cs | 74 +++++ OpenApiService/Kafka/Utils/MethodKeyPair.cs | 12 + .../Kafka/Utils/PendingMessagesBus.cs | 14 + .../Kafka/Utils/RecievedMessagesBus.cs | 13 + .../ConfigureConsumersException.cs | 13 + .../ConfigureMessageBusException.cs | 14 + .../ConsumerException/ConsumerException.cs | 18 ++ ...ConsumerRecievedMessageInvalidException.cs | 18 ++ .../ConsumerTopicUnavailableException.cs | 18 ++ .../KafkaException/MyKafkaException.cs | 21 ++ .../MessageProduceException.cs | 18 ++ .../ProducerExceptions/ProducerException.cs | 21 ++ .../TopicExceptions/CheckTopicException.cs | 18 ++ .../TopicExceptions/CreateTopicException.cs | 18 ++ .../TopicExceptions/TopicException.cs | 18 ++ OpenApiService/OpenApiService.csproj | 25 +- OpenApiService/Program.cs | 6 +- OpenApiService/Utils/Logging.cs | 41 +++ 20 files changed, 757 insertions(+), 2 deletions(-) create mode 100644 OpenApiService/Kafka/KafkaRequestService.cs create mode 100644 OpenApiService/Kafka/KafkaService.cs create mode 100644 OpenApiService/Kafka/KafkaTopicManager.cs create mode 100644 OpenApiService/Kafka/Utils/MethodKeyPair.cs create mode 100644 OpenApiService/Kafka/Utils/PendingMessagesBus.cs create mode 100644 OpenApiService/Kafka/Utils/RecievedMessagesBus.cs create mode 100644 OpenApiService/KafkaException/ConfigurationException/ConfigureConsumersException.cs create mode 100644 OpenApiService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs create mode 100644 OpenApiService/KafkaException/ConsumerException/ConsumerException.cs create mode 100644 OpenApiService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs create mode 100644 OpenApiService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs create mode 100644 OpenApiService/KafkaException/MyKafkaException.cs create mode 100644 OpenApiService/KafkaException/ProducerExceptions/MessageProduceException.cs create mode 100644 OpenApiService/KafkaException/ProducerExceptions/ProducerException.cs create mode 100644 OpenApiService/KafkaException/TopicExceptions/CheckTopicException.cs create mode 100644 OpenApiService/KafkaException/TopicExceptions/CreateTopicException.cs create mode 100644 OpenApiService/KafkaException/TopicExceptions/TopicException.cs create mode 100644 OpenApiService/Utils/Logging.cs diff --git a/OpenApiService/Kafka/KafkaRequestService.cs b/OpenApiService/Kafka/KafkaRequestService.cs new file mode 100644 index 0000000..4b628d9 --- /dev/null +++ b/OpenApiService/Kafka/KafkaRequestService.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Confluent.Kafka; +using OpenApiService.Kafka; +using OpenApiService.KafkaException; +using OpenApiService.KafkaException.ConsumerException; +using OpenApiService.Kafka.Utils; +using OpenApiService.KafkaException.ConfigurationException; + +namespace OpenApiService.Kafka; + +public class KafkaRequestService +{ + private readonly IProducer _producer; + private readonly ILogger _logger; + private readonly KafkaTopicManager _kafkaTopicManager; + private readonly HashSet _pendingMessagesBus; + private readonly HashSet _recievedMessagesBus; + private readonly HashSet> _consumerPool; + public KafkaRequestService( + IProducer producer, + ILogger logger, + KafkaTopicManager kafkaTopicManager, + List responseTopics, + List requestsTopics) + { + _producer = producer; + _logger = logger; + _kafkaTopicManager = kafkaTopicManager; + _recievedMessagesBus = ConfigureRecievedMessages(responseTopics); + _pendingMessagesBus = ConfigurePendingMessages(requestsTopics); + _consumerPool = ConfigureConsumers(responseTopics.Count()); + + } + public void BeginRecieving(List responseTopics) + { + int topicCount = 0; + foreach(var consumer in _consumerPool) + { + + Thread thread = new Thread( x=>{ + Consume(consumer,responseTopics[topicCount]); + }); + thread.Start(); + topicCount++; + } + } + + private HashSet> ConfigureConsumers(int amount) + { + try + { + if(amount<=0) + { + throw new ConfigureConsumersException(" Amount of consumers must be above 0!"); + } + HashSet> consumers = new HashSet>(); + for (int i = 0; i < amount; i++) + { + consumers.Add( + new ConsumerBuilder( + new ConsumerConfig() + { + BootstrapServers = Environment.GetEnvironmentVariable("KAFKA_BROKERS"), + GroupId = "gatewayConsumer"+Guid.NewGuid().ToString(), + EnableAutoCommit = true, + AutoCommitIntervalMs = 10, + EnableAutoOffsetStore = true, + AutoOffsetReset = AutoOffsetReset.Earliest + + } + ).Build() + ); + } + return consumers; + } + catch (Exception ex) + { + if (ex is MyKafkaException) + { + _logger.LogError(ex, "Error configuring consumers"); + throw new ProducerException("Error configuring consumers",ex); + } + throw; + } + + } + private HashSet ConfigurePendingMessages(List ResponseTopics) + { + if(ResponseTopics.Count == 0) + { + throw new ConfigureMessageBusException("At least one requests topic must e provided!"); + } + var PendingMessages = new HashSet(); + foreach(var requestTopic in ResponseTopics) + { + PendingMessages.Add(new PendingMessagesBus(){ TopicName=requestTopic, MessageKeys = new HashSet()}); + } + return PendingMessages; + } + private HashSet ConfigureRecievedMessages(List ResponseTopics) + { + if(ResponseTopics.Count == 0) + { + throw new ConfigureMessageBusException("At least one response topic must e provided!"); + } + HashSet Responses = new HashSet(); + foreach(var RequestTopic in ResponseTopics) + { + Responses.Add(new RecievedMessagesBus() { TopicName = RequestTopic, Messages = new HashSet>()}); + } + return Responses; + } + + private bool IsTopicAvailable(string topicName) + { + try + { + _logger.LogError("Unable to subscribe to topic"); + throw new ConsumerTopicUnavailableException("Topic unavailable"); + + } + catch (Exception e) + { + if (e is MyKafkaException) + { + _logger.LogError(e,"Error checking topic"); + throw new ConsumerException("Error checking topic",e); + } + _logger.LogError(e,"Unhandled error"); + throw; + } + } + + public bool IsMessageRecieved(string MessageKey) + { + try + { + return _recievedMessagesBus.Any(x=>x.Messages.Any(x=>x.Key==MessageKey)); + } + catch (Exception e) + { + throw new ConsumerException($"Recieved message bus error",e); + } + } + public async Task Produce(string topicName, Message message, string responseTopic) + { + try + { + bool IsTopicExists = IsTopicAvailable(topicName); + if (IsTopicExists && IsTopicPendingMessageBusExist( responseTopic)) + { + var deliveryResult = await _producer.ProduceAsync(topicName, message); + if (deliveryResult.Status == PersistenceStatus.Persisted) + { + _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); + + _pendingMessagesBus.FirstOrDefault(x=>x.TopicName == responseTopic)!.MessageKeys.Add(new MethodKeyPair(){ + MessageKey = message.Key, + MessageMethod = Encoding.UTF8.GetString(message.Headers.FirstOrDefault(x => x.Key.Equals("method"))!.GetValueBytes()) + }); + return true; + + + } + + _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); + throw new MessageProduceException("Message delivery status: Not persisted" + deliveryResult.Value); + + } + + bool IsTopicCreated = _kafkaTopicManager.CreateTopic(topicName, Convert.ToInt32(Environment.GetEnvironmentVariable("PARTITIONS_STANDART")), Convert.ToInt16(Environment.GetEnvironmentVariable("REPLICATION_FACTOR_STANDART"))); + if (IsTopicCreated && IsTopicPendingMessageBusExist( responseTopic)) + { + var deliveryResult = await _producer.ProduceAsync(topicName, message); + if (deliveryResult.Status == PersistenceStatus.Persisted) + { + _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); + _pendingMessagesBus.FirstOrDefault(x=>x.TopicName == responseTopic)!.MessageKeys.Add(new MethodKeyPair(){ + MessageKey = message.Key, + MessageMethod = Encoding.UTF8.GetString(message.Headers.FirstOrDefault(x => x.Key.Equals("method"))!.GetValueBytes()) + }); + return true; + } + + _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); + throw new MessageProduceException("Message delivery status: Not persisted"); + + } + _logger.LogError("Topic unavailable"); + throw new MessageProduceException("Topic unavailable"); + } + catch (Exception e) + { + if (e is MyKafkaException) + { + _logger.LogError(e, "Error producing message"); + throw new ProducerException("Error producing message",e); + } + throw; + } + } + private bool IsTopicPendingMessageBusExist(string responseTopic) + { + return _pendingMessagesBus.Any(x => x.TopicName == responseTopic); + } + private void Consume(IConsumer localConsumer,string topicName) + { + localConsumer.Subscribe(topicName); + while (true) + { + ConsumeResult result = localConsumer.Consume(); + + if (result != null) + { + try + { + if( _pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName)!.MessageKeys.Any(x=>x.MessageKey==result.Message.Key)) + { + if(result.Message.Headers.Any(x => x.Key.Equals("errors"))) + { + var errors = Encoding.UTF8.GetString(result.Message.Headers.FirstOrDefault(x => x.Key.Equals("errors"))!.GetValueBytes()); + _logger.LogError(errors); + + throw new ConsumerException(errors); + } + + MethodKeyPair pendingMessage = _pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName)!.MessageKeys.FirstOrDefault(x=>x.MessageKey==result.Message.Key)!; + if(_pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName)!.MessageKeys.Any(x=>x.MessageMethod== Encoding.UTF8.GetString(result.Message.Headers.FirstOrDefault(x => x.Key.Equals("method"))!.GetValueBytes()))) + { + + localConsumer.Commit(result); + _recievedMessagesBus.FirstOrDefault(x=>x.TopicName== topicName)!.Messages.Add(result.Message); + _pendingMessagesBus.FirstOrDefault(x=>x.TopicName==topicName)!.MessageKeys.Remove(pendingMessage); + } + _logger.LogError("Wrong message method"); + throw new ConsumerException("Wrong message method"); + } + } + catch (Exception e) + { + if (e is MyKafkaException) + { + _logger.LogError(e,"Consumer error"); + throw new ConsumerException("Consumer error ",e); + } + _logger.LogError(e,"Unhandled error"); + localConsumer.Commit(result); + throw; + } + + } + } + } +} diff --git a/OpenApiService/Kafka/KafkaService.cs b/OpenApiService/Kafka/KafkaService.cs new file mode 100644 index 0000000..e0dc3ed --- /dev/null +++ b/OpenApiService/Kafka/KafkaService.cs @@ -0,0 +1,121 @@ +using System.ComponentModel; +using System.Text; +using Confluent.Kafka; +using OpenApiService.KafkaException; +using OpenApiService.KafkaException.ConsumerException; +using Newtonsoft.Json; +namespace OpenApiService.Kafka; + +public abstract class KafkaService(ILogger logger, IProducer producer, KafkaTopicManager kafkaTopicManager) +{ + protected readonly IProducer _producer = producer; + protected readonly ILogger _logger = logger; + protected readonly KafkaTopicManager _kafkaTopicManager = kafkaTopicManager; + protected IConsumer?_consumer; + + protected void ConfigureConsumer(string topicName) + { + try + { + var config = new ConsumerConfig + { + GroupId = "test-consumer-group", + BootstrapServers = Environment.GetEnvironmentVariable("BOOTSTRAP_SERVERS"), + AutoOffsetReset = AutoOffsetReset.Earliest + }; + _consumer = new ConsumerBuilder(config).Build(); + if(IsTopicAvailable(topicName)) + { + _consumer.Subscribe(topicName); + } + throw new ConsumerTopicUnavailableException("Topic unavailable"); + } + catch (Exception e) + { + if (e is MyKafkaException) + { + _logger.LogError(e,"Error configuring consumer"); + throw new ConsumerException("Error configuring consumer",e); + } + _logger.LogError(e,"Unhandled error"); + throw; + } + } + private bool IsTopicAvailable(string topicName) + { + try + { + bool IsTopicExists = _kafkaTopicManager.CheckTopicExists(topicName); + if (IsTopicExists) + { + return IsTopicExists; + } + _logger.LogError("Unable to subscribe to topic"); + throw new ConsumerTopicUnavailableException("Topic unavailable"); + + } + catch (Exception e) + { + if (e is MyKafkaException) + { + _logger.LogError(e,"Error checking topic"); + throw new ConsumerException("Error checking topic",e); + } + _logger.LogError(e,"Unhandled error"); + throw; + } + } + public abstract Task Consume(); + public async Task Produce( string topicName,Message message) + { + try + { + bool IsTopicExists = IsTopicAvailable(topicName); + if (IsTopicExists) + { + var deliveryResult = await _producer.ProduceAsync(topicName, message); + if (deliveryResult.Status == PersistenceStatus.Persisted) + { + + _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); + return true; + } + + _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); + throw new MessageProduceException("Message delivery status: Not persisted" + deliveryResult.Value); + + } + + bool IsTopicCreated = _kafkaTopicManager.CreateTopic(topicName, Convert.ToInt32(Environment.GetEnvironmentVariable("PARTITIONS_STANDART")), Convert.ToInt16(Environment.GetEnvironmentVariable("REPLICATION_FACTOR_STANDART"))); + if (IsTopicCreated) + { + var deliveryResult = await _producer.ProduceAsync(topicName, message); + if (deliveryResult.Status == PersistenceStatus.Persisted) + { + _logger.LogInformation("Message delivery status: Persisted {Result}", deliveryResult.Value); + return true; + } + + _logger.LogError("Message delivery status: Not persisted {Result}", deliveryResult.Value); + throw new MessageProduceException("Message delivery status: Not persisted"); + + } + _logger.LogError("Topic unavailable"); + throw new MessageProduceException("Topic unavailable"); + } + catch (Exception e) + { + if (e is MyKafkaException) + { + _logger.LogError(e, "Error producing message"); + throw new ProducerException("Error producing message",e); + } + throw; + } + + + + } + + +} \ No newline at end of file diff --git a/OpenApiService/Kafka/KafkaTopicManager.cs b/OpenApiService/Kafka/KafkaTopicManager.cs new file mode 100644 index 0000000..a5134c5 --- /dev/null +++ b/OpenApiService/Kafka/KafkaTopicManager.cs @@ -0,0 +1,74 @@ +using Confluent.Kafka; +using Confluent.Kafka.Admin; +using OpenApiService.KafkaException; + +namespace OpenApiService.Kafka; + +public class KafkaTopicManager(IAdminClient adminClient) +{ + private readonly IAdminClient _adminClient = adminClient; + + /// + /// Checks if a Kafka topic with the specified name exists. + /// + /// The name of the topic to check. + /// True if the topic exists, false otherwise. + /// Thrown if the topic check fails. + public bool CheckTopicExists(string topicName) + { + try + { + var topicExists = _adminClient.GetMetadata(topicName, TimeSpan.FromSeconds(10)); + if (topicExists.Topics.Count == 0) + { + return false; + } + return true; + } + catch (Exception e) + { + + Console.WriteLine($"An error occurred: {e.Message}"); + throw new CheckTopicException("Failed to check topic"); + } + } + + /// + /// Creates a new Kafka topic with the specified name, number of partitions, and replication factor. + /// + /// The name of the topic to create. + /// The number of partitions for the topic. + /// The replication factor for the topic. + /// True if the topic was successfully created, false otherwise. + /// Thrown if the topic creation fails. + public bool CreateTopic(string topicName, int numPartitions, short replicationFactor) + { + try + { + + var result = _adminClient.CreateTopicsAsync(new TopicSpecification[] + { + new() { + Name = topicName, + NumPartitions = numPartitions, + ReplicationFactor = replicationFactor, + Configs = new Dictionary + { + { "min.insync.replicas", "2" } + }} + }); + if (result.IsCompleted) + { + return true; + } + throw new CreateTopicException("Failed to create topic"); + } + catch (Exception e) + { + Console.WriteLine(e); + throw new CreateTopicException("Failed to create topic"); + } + } + + +} \ No newline at end of file diff --git a/OpenApiService/Kafka/Utils/MethodKeyPair.cs b/OpenApiService/Kafka/Utils/MethodKeyPair.cs new file mode 100644 index 0000000..7614e33 --- /dev/null +++ b/OpenApiService/Kafka/Utils/MethodKeyPair.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Kafka.Utils; + +public class MethodKeyPair +{ + public string MessageKey { get; set; } = null!; + public string MessageMethod {get;set;} = null!; +} diff --git a/OpenApiService/Kafka/Utils/PendingMessagesBus.cs b/OpenApiService/Kafka/Utils/PendingMessagesBus.cs new file mode 100644 index 0000000..f76dc69 --- /dev/null +++ b/OpenApiService/Kafka/Utils/PendingMessagesBus.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using OpenApiService.Kafka.Utils; + +namespace OpenApiService.Kafka; + + public class PendingMessagesBus + { + public string TopicName {get;set;} = null!; + public HashSet MessageKeys {get;set;} = null!; + } diff --git a/OpenApiService/Kafka/Utils/RecievedMessagesBus.cs b/OpenApiService/Kafka/Utils/RecievedMessagesBus.cs new file mode 100644 index 0000000..2ca4142 --- /dev/null +++ b/OpenApiService/Kafka/Utils/RecievedMessagesBus.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Confluent.Kafka; + +namespace OpenApiService.Kafka; + + public class RecievedMessagesBus + { + public string TopicName { get; set; } = null!; + public HashSet> Messages { get; set;} = null!; + } diff --git a/OpenApiService/KafkaException/ConfigurationException/ConfigureConsumersException.cs b/OpenApiService/KafkaException/ConfigurationException/ConfigureConsumersException.cs new file mode 100644 index 0000000..f1ec07a --- /dev/null +++ b/OpenApiService/KafkaException/ConfigurationException/ConfigureConsumersException.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using OpenApiService.KafkaException; + +namespace OpenApiService.KafkaException.ConfigurationException; +public class ConfigureConsumersException : MyKafkaException +{ + public ConfigureConsumersException() {} + public ConfigureConsumersException(string message) : base(message) {} + public ConfigureConsumersException(string message, System.Exception inner) : base(message, inner) {} +} diff --git a/OpenApiService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs b/OpenApiService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs new file mode 100644 index 0000000..03217b2 --- /dev/null +++ b/OpenApiService/KafkaException/ConfigurationException/ConfigureMessageBusException.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using OpenApiService.KafkaException; + +namespace OpenApiService.KafkaException.ConfigurationException; + +public class ConfigureMessageBusException : MyKafkaException +{ + public ConfigureMessageBusException() {} + public ConfigureMessageBusException(string message) : base(message) {} + public ConfigureMessageBusException(string message, System.Exception inner) : base(message, inner) {} +} diff --git a/OpenApiService/KafkaException/ConsumerException/ConsumerException.cs b/OpenApiService/KafkaException/ConsumerException/ConsumerException.cs new file mode 100644 index 0000000..13b9c22 --- /dev/null +++ b/OpenApiService/KafkaException/ConsumerException/ConsumerException.cs @@ -0,0 +1,18 @@ +namespace OpenApiService.KafkaException.ConsumerException; + +public class ConsumerException : MyKafkaException +{ + public ConsumerException() + { + } + + public ConsumerException(string message) + : base(message) + { + } + + public ConsumerException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs b/OpenApiService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs new file mode 100644 index 0000000..b32b11c --- /dev/null +++ b/OpenApiService/KafkaException/ConsumerException/ConsumerRecievedMessageInvalidException.cs @@ -0,0 +1,18 @@ +namespace OpenApiService.KafkaException.ConsumerException; + +public class ConsumerRecievedMessageInvalidException : ConsumerException +{ + public ConsumerRecievedMessageInvalidException() + { + } + + public ConsumerRecievedMessageInvalidException(string message) + : base(message) + { + } + + public ConsumerRecievedMessageInvalidException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs b/OpenApiService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs new file mode 100644 index 0000000..6f41c1a --- /dev/null +++ b/OpenApiService/KafkaException/ConsumerException/ConsumerTopicUnavailableException.cs @@ -0,0 +1,18 @@ +namespace OpenApiService.KafkaException.ConsumerException; + +public class ConsumerTopicUnavailableException : ConsumerException +{ + public ConsumerTopicUnavailableException() + { + } + + public ConsumerTopicUnavailableException(string message) + : base(message) + { + } + + public ConsumerTopicUnavailableException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/MyKafkaException.cs b/OpenApiService/KafkaException/MyKafkaException.cs new file mode 100644 index 0000000..51fd401 --- /dev/null +++ b/OpenApiService/KafkaException/MyKafkaException.cs @@ -0,0 +1,21 @@ +namespace OpenApiService.KafkaException; + +public class MyKafkaException : Exception +{ + public MyKafkaException() + { + + } + + public MyKafkaException(string message) + : base(message) + { + + } + + public MyKafkaException(string message, Exception innerException) + : base(message, innerException) + { + + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/ProducerExceptions/MessageProduceException.cs b/OpenApiService/KafkaException/ProducerExceptions/MessageProduceException.cs new file mode 100644 index 0000000..d8993ea --- /dev/null +++ b/OpenApiService/KafkaException/ProducerExceptions/MessageProduceException.cs @@ -0,0 +1,18 @@ +namespace KafkaTestLib.KafkaException; + +public class MessageProduceException : ProducerException +{ + public MessageProduceException() + { + } + + public MessageProduceException(string message) + : base(message) + { + } + + public MessageProduceException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/ProducerExceptions/ProducerException.cs b/OpenApiService/KafkaException/ProducerExceptions/ProducerException.cs new file mode 100644 index 0000000..224598d --- /dev/null +++ b/OpenApiService/KafkaException/ProducerExceptions/ProducerException.cs @@ -0,0 +1,21 @@ +namespace KafkaTestLib.KafkaException; + +public class ProducerException : MyKafkaException +{ + public ProducerException() + { + + } + + public ProducerException(string message) + : base(message) + { + + } + + public ProducerException(string message, Exception innerException) + : base(message, innerException) + { + + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/TopicExceptions/CheckTopicException.cs b/OpenApiService/KafkaException/TopicExceptions/CheckTopicException.cs new file mode 100644 index 0000000..d234c67 --- /dev/null +++ b/OpenApiService/KafkaException/TopicExceptions/CheckTopicException.cs @@ -0,0 +1,18 @@ +namespace KafkaTestLib.KafkaException; + +public class CheckTopicException : TopicException +{ + public CheckTopicException() + { + } + + public CheckTopicException(string message) + : base(message) + { + } + + public CheckTopicException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/TopicExceptions/CreateTopicException.cs b/OpenApiService/KafkaException/TopicExceptions/CreateTopicException.cs new file mode 100644 index 0000000..f812979 --- /dev/null +++ b/OpenApiService/KafkaException/TopicExceptions/CreateTopicException.cs @@ -0,0 +1,18 @@ +namespace OpenApiService.KafkaException; + +public class CreateTopicException : TopicException +{ + public CreateTopicException() + { + } + + public CreateTopicException(string message) + : base(message) + { + } + + public CreateTopicException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/KafkaException/TopicExceptions/TopicException.cs b/OpenApiService/KafkaException/TopicExceptions/TopicException.cs new file mode 100644 index 0000000..988d17a --- /dev/null +++ b/OpenApiService/KafkaException/TopicExceptions/TopicException.cs @@ -0,0 +1,18 @@ +namespace KafkaTestLib.KafkaException; + +public class TopicException : MyKafkaException +{ + public TopicException() + { + } + + public TopicException(string message) + : base(message) + { + } + + public TopicException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/OpenApiService/OpenApiService.csproj b/OpenApiService/OpenApiService.csproj index 1b28a01..042b130 100644 --- a/OpenApiService/OpenApiService.csproj +++ b/OpenApiService/OpenApiService.csproj @@ -5,5 +5,28 @@ enable enable - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OpenApiService/Program.cs b/OpenApiService/Program.cs index 1760df1..34bead7 100644 --- a/OpenApiService/Program.cs +++ b/OpenApiService/Program.cs @@ -1,6 +1,10 @@ +using OpenApiService.Utils; +using Serilog; + var builder = WebApplication.CreateBuilder(args); +Logging.configureLogging(); +builder.Host.UseSerilog(); var app = builder.Build(); -app.MapGet("/", () => "Hello World!"); app.Run(); diff --git a/OpenApiService/Utils/Logging.cs b/OpenApiService/Utils/Logging.cs new file mode 100644 index 0000000..b55fff8 --- /dev/null +++ b/OpenApiService/Utils/Logging.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Serilog; +using Serilog.Exceptions; +using Serilog.Sinks.OpenSearch; + +namespace OpenApiService.Utils +{ + public static class Logging + { + + static OpenSearchSinkOptions _configureOpenSearchSink(IConfiguration configuration,string environment){ + return new OpenSearchSinkOptions(new Uri(configuration["OpenSearchConfiguration:Uri"]!)) + { + AutoRegisterTemplate = true, + IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name!.ToLower().Replace(".","-")}-{environment.ToLower()}-{DateTime.UtcNow:yyyy-MM-DD}", + NumberOfReplicas =1, + NumberOfShards = 1 + }; + } + + public static void configureLogging(){ + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"; + var configuration = new ConfigurationBuilder() + .AddJsonFile("appsettings.json",optional:false,reloadOnChange:true).Build(); + Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .Enrich.WithExceptionDetails() + .WriteTo.Debug() + .WriteTo.Console() + .WriteTo.OpenSearch(_configureOpenSearchSink(configuration,environment)) + .Enrich.WithProperty("Environment",environment) + .ReadFrom.Configuration(configuration) + .CreateLogger(); + } + } + +} \ No newline at end of file From c5663e2e22eb0665a32f388fc4d2bcda4affa8d9 Mon Sep 17 00:00:00 2001 From: ereshkigal Date: Sun, 3 Nov 2024 00:58:33 +0300 Subject: [PATCH 4/7] added universal request sender --- .../RequestSender/BuildUriException.cs | 14 + .../RequestSender/RequestSenderException.cs | 14 + .../RequestSender/SendRequestException.cs | 15 + .../Requests/ICreditOrganizationService.cs | 12 + OpenApiService/Utils/Logging.cs | 54 ++-- OpenApiService/Utils/RequestSender.cs | 265 ++++++++++++++++++ 6 files changed, 346 insertions(+), 28 deletions(-) create mode 100644 OpenApiService/Exceptions/RequestSender/BuildUriException.cs create mode 100644 OpenApiService/Exceptions/RequestSender/RequestSenderException.cs create mode 100644 OpenApiService/Exceptions/RequestSender/SendRequestException.cs create mode 100644 OpenApiService/Services/Requests/ICreditOrganizationService.cs create mode 100644 OpenApiService/Utils/RequestSender.cs diff --git a/OpenApiService/Exceptions/RequestSender/BuildUriException.cs b/OpenApiService/Exceptions/RequestSender/BuildUriException.cs new file mode 100644 index 0000000..d4e627b --- /dev/null +++ b/OpenApiService/Exceptions/RequestSender/BuildUriException.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Exceptions.RequestSender; +[System.Serializable] +public class BuildUriException : RequestSenderException +{ + public BuildUriException() { } + public BuildUriException(string message) : base(message) { } + public BuildUriException(string message, System.Exception inner) : base(message, inner) { } + +} diff --git a/OpenApiService/Exceptions/RequestSender/RequestSenderException.cs b/OpenApiService/Exceptions/RequestSender/RequestSenderException.cs new file mode 100644 index 0000000..ae357ea --- /dev/null +++ b/OpenApiService/Exceptions/RequestSender/RequestSenderException.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Exceptions.RequestSender; + +[System.Serializable] +public class RequestSenderException : System.Exception +{ + public RequestSenderException() { } + public RequestSenderException(string message) : base(message) { } + public RequestSenderException(string message, System.Exception inner) : base(message, inner) { } +} diff --git a/OpenApiService/Exceptions/RequestSender/SendRequestException.cs b/OpenApiService/Exceptions/RequestSender/SendRequestException.cs new file mode 100644 index 0000000..e87178e --- /dev/null +++ b/OpenApiService/Exceptions/RequestSender/SendRequestException.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Exceptions.RequestSender; + +[System.Serializable] +public class SendRequestException : RequestSenderException +{ + public SendRequestException() { } + public SendRequestException(string message) : base(message) { } + public SendRequestException(string message, System.Exception inner) : base(message, inner) { } + +} diff --git a/OpenApiService/Services/Requests/ICreditOrganizationService.cs b/OpenApiService/Services/Requests/ICreditOrganizationService.cs new file mode 100644 index 0000000..37fea41 --- /dev/null +++ b/OpenApiService/Services/Requests/ICreditOrganizationService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Services.Requests +{ + public interface ICreditOrganizationService + { + + } +} \ No newline at end of file diff --git a/OpenApiService/Utils/Logging.cs b/OpenApiService/Utils/Logging.cs index b55fff8..c970242 100644 --- a/OpenApiService/Utils/Logging.cs +++ b/OpenApiService/Utils/Logging.cs @@ -7,35 +7,33 @@ using Serilog.Exceptions; using Serilog.Sinks.OpenSearch; -namespace OpenApiService.Utils +namespace OpenApiService.Utils; +public static class Logging { - public static class Logging - { - - static OpenSearchSinkOptions _configureOpenSearchSink(IConfiguration configuration,string environment){ - return new OpenSearchSinkOptions(new Uri(configuration["OpenSearchConfiguration:Uri"]!)) - { - AutoRegisterTemplate = true, - IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name!.ToLower().Replace(".","-")}-{environment.ToLower()}-{DateTime.UtcNow:yyyy-MM-DD}", - NumberOfReplicas =1, - NumberOfShards = 1 - }; - } + + static OpenSearchSinkOptions _configureOpenSearchSink(IConfiguration configuration,string environment){ + return new OpenSearchSinkOptions(new Uri(configuration["OpenSearchConfiguration:Uri"]!)) + { + AutoRegisterTemplate = true, + IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name!.ToLower().Replace(".","-")}-{environment.ToLower()}-{DateTime.UtcNow:yyyy-MM-DD}", + NumberOfReplicas =1, + NumberOfShards = 1 + }; + } - public static void configureLogging(){ - var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"; - var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings.json",optional:false,reloadOnChange:true).Build(); - Log.Logger = new LoggerConfiguration() - .Enrich.FromLogContext() - .Enrich.WithExceptionDetails() - .WriteTo.Debug() - .WriteTo.Console() - .WriteTo.OpenSearch(_configureOpenSearchSink(configuration,environment)) - .Enrich.WithProperty("Environment",environment) - .ReadFrom.Configuration(configuration) - .CreateLogger(); - } + public static void configureLogging(){ + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"; + var configuration = new ConfigurationBuilder() + .AddJsonFile("appsettings.json",optional:false,reloadOnChange:true).Build(); + Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .Enrich.WithExceptionDetails() + .WriteTo.Debug() + .WriteTo.Console() + .WriteTo.OpenSearch(_configureOpenSearchSink(configuration,environment)) + .Enrich.WithProperty("Environment",environment) + .ReadFrom.Configuration(configuration) + .CreateLogger(); } +} -} \ No newline at end of file diff --git a/OpenApiService/Utils/RequestSender.cs b/OpenApiService/Utils/RequestSender.cs new file mode 100644 index 0000000..56fd61d --- /dev/null +++ b/OpenApiService/Utils/RequestSender.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using System.Web; +using Newtonsoft.Json; +using OpenApiService.Exceptions.RequestSender; + +namespace OpenApiService.Utils; +public class RequestSender(ILogger logger, HttpClient client) +{ + private readonly ILogger _logger = logger; + private readonly HttpClient _client = client; + public string BuildRequestUri(string url, string? pathParameter, Dictionary? queryParameters) + { + try + { + var uriBuilder = new UriBuilder(url + pathParameter); + + if(queryParameters !=null) + { + var query = HttpUtility.ParseQueryString(uriBuilder.Query); + _logger.LogDebug("Building uri with query paramete"); + foreach(var queryParameter in queryParameters) + { + query[queryParameter.Key]=queryParameter.Value.ToString(); + } + uriBuilder.Query = query.ToString(); + } + _logger.LogDebug("Uri built successfuly!"); + return uriBuilder.ToString(); + + } + catch (Exception ex) + { + var exception = new BuildUriException("Failed to build uri!", ex); + _logger.LogError(exception,"Failed to build uri!"); + throw exception; + } + + } + public async Task SendGetRequestAsync( Dictionary>? headers, string uri ) + { + try + { + _logger.LogDebug("Building get request"); + var request = new HttpRequestMessage + { + Method = HttpMethod.Get, + RequestUri = new Uri(uri) + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + catch (Exception ex) + { + var exception = new SendRequestException("Failed to build or send request!", ex); + _logger.LogError(exception,"Failed to build or send request!"); + throw exception; + } + } + public async Task SendPostRequestAsync(object? message, Dictionary>? headers, string uri ) + { + try + { + _logger.LogDebug("Building post request"); + if(message == null) + { + var request = new HttpRequestMessage + { + Method = HttpMethod.Post, + RequestUri = new Uri(uri) + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + else + { + using StringContent jsonContent = new( + JsonConvert.SerializeObject(message), + Encoding.UTF8, + "application/json"); + var request = new HttpRequestMessage + { + Method = HttpMethod.Post, + RequestUri = new Uri(uri), + Content = jsonContent + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + + } + catch (Exception ex) + { + var exception = new SendRequestException("Failed to build or send request!", ex); + _logger.LogError(exception,"Failed to build or send request!"); + throw exception; + } + } + public async Task SendPutRequestAsync(object? message, Dictionary>? headers, string uri ) + { + try + { + _logger.LogDebug("Building put request"); + if(message == null) + { + var request = new HttpRequestMessage + { + Method = HttpMethod.Put, + RequestUri = new Uri(uri) + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + else + { + using StringContent jsonContent = new( + JsonConvert.SerializeObject(message), + Encoding.UTF8, + "application/json"); + var request = new HttpRequestMessage + { + Method = HttpMethod.Put, + RequestUri = new Uri(uri), + Content = jsonContent + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + + } + catch (Exception ex) + { + var exception = new SendRequestException("Failed to build or send request!", ex); + _logger.LogError(exception,"Failed to build or send request!"); + throw exception; + } + } + public async Task SendDeleteRequestAsync(object? message, Dictionary>? headers, string uri ) + { + try + { + _logger.LogDebug("Building delete request"); + if(message == null) + { + var request = new HttpRequestMessage + { + Method = HttpMethod.Delete, + RequestUri = new Uri(uri) + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + else + { + using StringContent jsonContent = new( + JsonConvert.SerializeObject(message), + Encoding.UTF8, + "application/json"); + var request = new HttpRequestMessage + { + Method = HttpMethod.Delete, + RequestUri = new Uri(uri), + Content = jsonContent + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + + } + catch (Exception ex) + { + var exception = new SendRequestException("Failed to build or send request!", ex); + _logger.LogError(exception,"Failed to build or send request!"); + throw exception; + } + } + public async Task SendPatchRequestAsync(object? message, Dictionary>? headers, string uri ) + { + try + { + _logger.LogDebug("Building patch request"); + if(message == null) + { + var request = new HttpRequestMessage + { + Method = HttpMethod.Patch, + RequestUri = new Uri(uri) + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + else + { + using StringContent jsonContent = new( + JsonConvert.SerializeObject(message), + Encoding.UTF8, + "application/json"); + var request = new HttpRequestMessage + { + Method = HttpMethod.Patch, + RequestUri = new Uri(uri), + Content = jsonContent + }; + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } + var response = await _client.SendAsync(request); + _logger.LogDebug("Response aquired successfully"); + return response; + } + + } + catch (Exception ex) + { + var exception = new SendRequestException("Failed to build or send request!", ex); + _logger.LogError(exception,"Failed to build or send request!"); + throw exception; + } + } +} \ No newline at end of file From 6e788ad3409d6291d43810c1888b590c0c04964c Mon Sep 17 00:00:00 2001 From: ereshkigal Date: Sun, 3 Nov 2024 09:07:06 +0300 Subject: [PATCH 5/7] small request sender fix --- OpenApiService/Utils/RequestSender.cs | 62 +++++++++++++++++++-------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/OpenApiService/Utils/RequestSender.cs b/OpenApiService/Utils/RequestSender.cs index 56fd61d..1ddee9b 100644 --- a/OpenApiService/Utils/RequestSender.cs +++ b/OpenApiService/Utils/RequestSender.cs @@ -78,9 +78,12 @@ public async Task SendPostRequestAsync(object? message, Dic Method = HttpMethod.Post, RequestUri = new Uri(uri) }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -89,18 +92,21 @@ public async Task SendPostRequestAsync(object? message, Dic else { using StringContent jsonContent = new( - JsonConvert.SerializeObject(message), - Encoding.UTF8, - "application/json"); + JsonConvert.SerializeObject(message), + Encoding.UTF8, + "application/json"); var request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri(uri), Content = jsonContent }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -127,9 +133,12 @@ public async Task SendPutRequestAsync(object? message, Dict Method = HttpMethod.Put, RequestUri = new Uri(uri) }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -147,9 +156,12 @@ public async Task SendPutRequestAsync(object? message, Dict RequestUri = new Uri(uri), Content = jsonContent }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -176,9 +188,12 @@ public async Task SendDeleteRequestAsync(object? message, D Method = HttpMethod.Delete, RequestUri = new Uri(uri) }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -196,9 +211,12 @@ public async Task SendDeleteRequestAsync(object? message, D RequestUri = new Uri(uri), Content = jsonContent }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -225,9 +243,12 @@ public async Task SendPatchRequestAsync(object? message, Di Method = HttpMethod.Patch, RequestUri = new Uri(uri) }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); @@ -245,9 +266,12 @@ public async Task SendPatchRequestAsync(object? message, Di RequestUri = new Uri(uri), Content = jsonContent }; - foreach(var header in headers) + if(headers != null) { - request.Headers.Add(header.Key,header.Value); + foreach(var header in headers) + { + request.Headers.Add(header.Key,header.Value); + } } var response = await _client.SendAsync(request); _logger.LogDebug("Response aquired successfully"); From ac7f1328a1fb296526b17a89e9da57cde4e1c331 Mon Sep 17 00:00:00 2001 From: ereshkigal Date: Sun, 3 Nov 2024 10:56:01 +0300 Subject: [PATCH 6/7] Preparing models to serve work with open API --- .../Responses/CreditOrganization/Brand.cs | 18 +++++++++++++ .../CreditOrganization/GetProductsResponse.cs | 18 +++++++++++++ .../Responses/CreditOrganization/Link.cs | 13 ++++++++++ .../Responses/CreditOrganization/Meta.cs | 12 +++++++++ .../Responses/CreditOrganization/Product.cs | 25 +++++++++++++++++++ .../CreditOrganization/ProductData.cs | 12 +++++++++ .../Models/Responses/Error/Error.cs | 18 +++++++++++++ .../Models/Responses/Error/ErrorResponse.cs | 19 ++++++++++++++ OpenApiService/Utils/RequestSender.cs | 7 ++++-- 9 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Brand.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Link.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Meta.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Product.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/ProductData.cs create mode 100644 OpenApiService/Models/Responses/Error/Error.cs create mode 100644 OpenApiService/Models/Responses/Error/ErrorResponse.cs diff --git a/OpenApiService/Models/Responses/CreditOrganization/Brand.cs b/OpenApiService/Models/Responses/CreditOrganization/Brand.cs new file mode 100644 index 0000000..5ae22e8 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Brand.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization; + +public class Brand +{ + [Required] + [StringLength(100)] + public string brandName { get; set; } = null!; + + [Required] + [Url] + public string applicationUri { get; set; } = null!; +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs b/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs new file mode 100644 index 0000000..3a70320 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class GetProductsResponse + { + [Required] + public ProductData Data { get; set; } = null!; + [Required] + public List Links{ get; set; } = null!; + [Required] + public Meta Meta{ get; set; } = null!; + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/Link.cs b/OpenApiService/Models/Responses/CreditOrganization/Link.cs new file mode 100644 index 0000000..ff9dd13 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Link.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization; +public class Link +{ + [Required] + [Url] + public string self { get; set; } = null!; +} diff --git a/OpenApiService/Models/Responses/CreditOrganization/Meta.cs b/OpenApiService/Models/Responses/CreditOrganization/Meta.cs new file mode 100644 index 0000000..8071f17 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Meta.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization; +public class Meta +{ + [Required] + public int TotalPages { get; set; } +} diff --git a/OpenApiService/Models/Responses/CreditOrganization/Product.cs b/OpenApiService/Models/Responses/CreditOrganization/Product.cs new file mode 100644 index 0000000..5e9c796 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Product.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization; +public class Product +{ + [Required] + public Guid ProductId { get; set; } + + [Required] + [StringLength(100)] + public string ProductName { get; set; } = null!; + + [Required] + public string ProductType { get; set; } = null!; + + [Required] + public string ProductVersion { get; set; } = null!; + + [Required] + public List Brand { get; set; } = null!; +} diff --git a/OpenApiService/Models/Responses/CreditOrganization/ProductData.cs b/OpenApiService/Models/Responses/CreditOrganization/ProductData.cs new file mode 100644 index 0000000..188f8fa --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/ProductData.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization; +public class ProductData +{ + [Required] + public Product Data { get; set; } = null!; +} diff --git a/OpenApiService/Models/Responses/Error/Error.cs b/OpenApiService/Models/Responses/Error/Error.cs new file mode 100644 index 0000000..9efee31 --- /dev/null +++ b/OpenApiService/Models/Responses/Error/Error.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses; +public class Error +{ + [Required] + public string errorCode { get; set; } = null!; + [Required] + public string message { get; set; } = null!; + [Required] + public string path { get; set; } = null!; + [Required] + public string url { get; set; } = null!; +} diff --git a/OpenApiService/Models/Responses/Error/ErrorResponse.cs b/OpenApiService/Models/Responses/Error/ErrorResponse.cs new file mode 100644 index 0000000..7c64944 --- /dev/null +++ b/OpenApiService/Models/Responses/Error/ErrorResponse.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses; +public class ErrorResponse +{ + [Required] + public string code { get; set; } = null!; + [Required] + public string id { get; set; } = null!; + [Required] + public string message { get; set; } = null!; + [Required] + public List Errors { get; set; } = null!; +} + diff --git a/OpenApiService/Utils/RequestSender.cs b/OpenApiService/Utils/RequestSender.cs index 1ddee9b..50408ba 100644 --- a/OpenApiService/Utils/RequestSender.cs +++ b/OpenApiService/Utils/RequestSender.cs @@ -51,9 +51,12 @@ public async Task SendGetRequestAsync( Dictionary Date: Mon, 4 Nov 2024 14:59:20 +0300 Subject: [PATCH 7/7] ready to serve products methods --- .../CreditOrganization/CreditInterest.cs | 16 +++++ .../CreditOrganization/DebitInterest.cs | 13 ++++ .../DebitInterestTierBand.cs | 24 +++++++ .../DebitInterestTierBandSet.cs | 22 ++++++ .../CreditOrganization/DeliveryRegion.cs | 18 +++++ .../DeliveryRegionAndAddress.cs | 14 ++++ .../CreditOrganization/Eligibility.cs | 20 ++++++ .../CreditOrganization/FeatureAndBenefit.cs | 17 +++++ .../FeatureAndBenefitGroup.cs | 24 +++++++ .../FeatureAndBenefitItem.cs | 22 ++++++ .../FeatureBenefitEligibility.cs | 30 ++++++++ .../CreditOrganization/FeeApplicableRange.cs | 12 ++++ .../CreditOrganization/FeeChargeCap.cs | 17 +++++ .../CreditOrganization/FeeChargeDetail.cs | 34 +++++++++ .../CreditOrganization/GetProductsResponse.cs | 2 +- .../Responses/CreditOrganization/Insurance.cs | 22 ++++++ .../CreditOrganization/InterestFeesCharges.cs | 14 ++++ .../Responses/CreditOrganization/Links.cs | 22 ++++++ .../OtherApplicationFrequency.cs | 14 ++++ .../OtherEligibilityType.cs | 14 ++++ .../CreditOrganization/OtherFeesCharges.cs | 17 +++++ .../Responses/CreditOrganization/Overdraft.cs | 13 ++++ .../OverdraftFeeChargeCap.cs | 17 +++++ .../OverdraftFeeChargeDetail.cs | 25 +++++++ .../OverdraftFeesCharges.cs | 13 ++++ .../OverdraftTierBandSet.cs | 36 ++++++++++ .../CreditOrganization/PostalAdress.cs | 22 ++++++ .../Responses/CreditOrganization/Product.cs | 23 +++--- .../CreditOrganization/ProductDetails.cs | 25 +++++++ .../Responses/CreditOrganization/Repayment.cs | 20 ++++++ .../CreditOrganization/RepaymentFeeCharges.cs | 13 ++++ .../CreditOrganization/SupplementaryData.cs | 12 ++++ .../CreditOrganization/TierBandDeposit.cs | 72 +++++++++++++++++++ .../CreditOrganization/TierBandSetDeposit.cs | 23 ++++++ .../TierBandSetEligibility.cs | 30 ++++++++ 35 files changed, 721 insertions(+), 11 deletions(-) create mode 100644 OpenApiService/Models/Responses/CreditOrganization/CreditInterest.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/DebitInterest.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBand.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBandSet.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/DeliveryRegion.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/DeliveryRegionAndAddress.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Eligibility.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefit.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitGroup.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitItem.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeatureBenefitEligibility.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeeApplicableRange.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeeChargeCap.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/FeeChargeDetail.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Insurance.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/InterestFeesCharges.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Links.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OtherApplicationFrequency.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OtherEligibilityType.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OtherFeesCharges.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Overdraft.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeCap.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeDetail.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OverdraftFeesCharges.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/OverdraftTierBandSet.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/PostalAdress.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/ProductDetails.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/Repayment.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/RepaymentFeeCharges.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/SupplementaryData.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/TierBandDeposit.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/TierBandSetDeposit.cs create mode 100644 OpenApiService/Models/Responses/CreditOrganization/TierBandSetEligibility.cs diff --git a/OpenApiService/Models/Responses/CreditOrganization/CreditInterest.cs b/OpenApiService/Models/Responses/CreditOrganization/CreditInterest.cs new file mode 100644 index 0000000..de5a658 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/CreditInterest.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class CreditInterest + { + public List Comments { get; set; } + + public List TierBandSetDeposit { get; set; } + + + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/DebitInterest.cs b/OpenApiService/Models/Responses/CreditOrganization/DebitInterest.cs new file mode 100644 index 0000000..f2b450e --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/DebitInterest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class DebitInterest + { + public List Comments { get; set; } + public List DebitInterestTierBandSet { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBand.cs b/OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBand.cs new file mode 100644 index 0000000..25138f8 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBand.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class DebitInterestTierBand + { + public string AER { get; set; } = null!; + public List Comments { get; set; } = null!; + public string Identification { get; set; } = null!; + public string TierCurrency { get; set; } = null!; + public string TierValueMinimum { get; set; } = null!; + public string TierValueMaximum { get; set; } = null!; + public int TierValueMinTerm { get; set; } + public string MinTermPeriod { get; set; } = null!; + public int TierValueMaxTerm { get; set; } + public string MaxTermPeriod { get; set; } = null!; + public string InterestRate { get; set; } = null!; + public string InterestRateType { get; set; } = null!; + public List InterestFeesCharges { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBandSet.cs b/OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBandSet.cs new file mode 100644 index 0000000..c62b6f9 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/DebitInterestTierBandSet.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class DebitInterestTierBandSet + { + public string Identification { get; set; } + + public string TierBandMethod { get; set; } + + public string CalculationMethod { get; set; } + + public List Comments { get; set; } + + public List DebitInterestTierBand { get; set; } + + + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/DeliveryRegion.cs b/OpenApiService/Models/Responses/CreditOrganization/DeliveryRegion.cs new file mode 100644 index 0000000..cf2fd7d --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/DeliveryRegion.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class DeliveryRegion + +{ + + public List Comments { get; set; } + + public List DeliveryRegionAndAddress { get; set; } + +} +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/DeliveryRegionAndAddress.cs b/OpenApiService/Models/Responses/CreditOrganization/DeliveryRegionAndAddress.cs new file mode 100644 index 0000000..50ff5cb --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/DeliveryRegionAndAddress.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class DeliveryRegionAndAddress + { + public string AdministrationZone { get; set; } = null!; + public PostalAddress PostalAddress { get; set; } = null!; + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/Eligibility.cs b/OpenApiService/Models/Responses/CreditOrganization/Eligibility.cs new file mode 100644 index 0000000..2970236 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Eligibility.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class Eligibility + { + public string Name { get; set; } + public string Description { get; set; } + public string Type { get; set; } + public List Comments { get; set; } + public string Amount { get; set; } + public bool Indicator { get; set; } + public string Textual { get; set; } + public string Period { get; set; } + public List OtherEligibilityType { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefit.cs b/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefit.cs new file mode 100644 index 0000000..62a2f93 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefit.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeatureAndBenefit + +{ + + public List FeatureAndBenefitGroup { get; set; } + + public List FeatureAndBenefitItem { get; set; } + +} +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitGroup.cs b/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitGroup.cs new file mode 100644 index 0000000..9ee83a0 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitGroup.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeatureAndBenefitGroup + { + [Required] + public string Name { get; set; } = null!; + public string Type { get; set; } = null!; + public List Comments { get; set; } = null!; + public string BenefitGroupNominalValue { get; set; } = null!; + public string Fee { get; set; } = null!; + public string ApplicationFrequency { get; set; } = null!; + public OtherApplicationFrequency OtherApplicationFrequency { get; set; } + public string CalculationFrequency { get; set; } = null!; + public OtherCalculationFrequency OtherCalculationFrequency { get; set; } + public OtherType OtherType { get; set; } + public List FeatureBenefitEligibility { get; set; } = null!; + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitItem.cs b/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitItem.cs new file mode 100644 index 0000000..e4688cd --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeatureAndBenefitItem.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeatureAndBenefitItem + { + [Required] + public Guid Identification { get; set; } + public string Type { get; set; } = null!; + public string Name { get; set; } = null!; + public List Comments { get; set; } = null!; + public string Amount { get; set; } = null!; + public bool Indicator { get; set; } + public string Textual { get; set; } = null!; + public OtherType OtherType { get; set; } + public List FeatureBenefitEligibility { get; set; } = null!; + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeatureBenefitEligibility.cs b/OpenApiService/Models/Responses/CreditOrganization/FeatureBenefitEligibility.cs new file mode 100644 index 0000000..71849db --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeatureBenefitEligibility.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeatureBenefitEligibility + { + public string Name { get; set; } + + public string Description { get; set; } + + public string Type { get; set; } + + public List Comments { get; set; } + + public string Amount { get; set; } + + public bool Indicator { get; set; } + + public string Textual { get; set; } + + public string Period { get; set; } + + public List OtherEligibilityType { get; set; } + + + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeeApplicableRange.cs b/OpenApiService/Models/Responses/CreditOrganization/FeeApplicableRange.cs new file mode 100644 index 0000000..0ea8b93 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeeApplicableRange.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeeApplicableRange + { + + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeeChargeCap.cs b/OpenApiService/Models/Responses/CreditOrganization/FeeChargeCap.cs new file mode 100644 index 0000000..451ab06 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeeChargeCap.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeeChargeCap + { + public string FeeType { get; set; } + public string MinMaxType { get; set; } + public int FeeCapOccurrence { get; set; } + public string FeeCapAmount { get; set; } + public string CappingPeriod { get; set; } + public List Comments { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/FeeChargeDetail.cs b/OpenApiService/Models/Responses/CreditOrganization/FeeChargeDetail.cs new file mode 100644 index 0000000..afcca0f --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/FeeChargeDetail.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class FeeChargeDetail + { + public string FeeType { get; set; } + + public OtherFeeType OtherFeeType { get; set; } + + public string FeeAmount { get; set; } + + public string FeeRate { get; set; } + + public string FeeRateType { get; set; } + + public OtherFeeRateType OtherFeeRateType { get; set; } + + public string ApplicationFrequency { get; set; } + + public OtherApplicationFrequency OtherApplicationFrequency { get; set; } + + public string CalculationFrequency { get; set; } + + public OtherCalculationFrequency OtherCalculationFrequency { get; set; } + + public FeeApplicableRange FeeApplicableRange { get; set; } + + public List Comments { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs b/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs index 3a70320..ab0a094 100644 --- a/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs +++ b/OpenApiService/Models/Responses/CreditOrganization/GetProductsResponse.cs @@ -11,7 +11,7 @@ public class GetProductsResponse [Required] public ProductData Data { get; set; } = null!; [Required] - public List Links{ get; set; } = null!; + public List Links { get; set; } = null!; [Required] public Meta Meta{ get; set; } = null!; } diff --git a/OpenApiService/Models/Responses/CreditOrganization/Insurance.cs b/OpenApiService/Models/Responses/CreditOrganization/Insurance.cs new file mode 100644 index 0000000..6a856e0 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Insurance.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class Insurance + { + [Required] + public string InsuranceId { get; set; } = null!; + [Required] + public string InsuranceName { get; set; } = null!; + public List Comments { get; set; } = null!; + public string CompanyName { get; set; } = null!; + public string AmountRate { get; set; } = null!; + [Url] + public string AgreementUrl { get; set; } = null!; + public List RiskComments { get; set; } = null!; + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/InterestFeesCharges.cs b/OpenApiService/Models/Responses/CreditOrganization/InterestFeesCharges.cs new file mode 100644 index 0000000..1094b6a --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/InterestFeesCharges.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class InterestFeesCharges + { + public List FeeChargeDetail { get; set; } + + public List FeeChargeCap { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/Links.cs b/OpenApiService/Models/Responses/CreditOrganization/Links.cs new file mode 100644 index 0000000..b7ad808 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Links.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class Links + { + [Url] + public string Self { get; set; } + [Url] + public string First { get; set; } + [Url] + public string Prev { get; set; } + [Url] + public string Next { get; set; } + [Url] + public string Last { get; set; } + } +} diff --git a/OpenApiService/Models/Responses/CreditOrganization/OtherApplicationFrequency.cs b/OpenApiService/Models/Responses/CreditOrganization/OtherApplicationFrequency.cs new file mode 100644 index 0000000..dc8a511 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OtherApplicationFrequency.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class Other + { + public string Code { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/OtherEligibilityType.cs b/OpenApiService/Models/Responses/CreditOrganization/OtherEligibilityType.cs new file mode 100644 index 0000000..655c24c --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OtherEligibilityType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class OtherEligibilityType + { + public string Code { get; set; } = null!; + public string Name { get; set; } = null!; + public string Description { get; set; } = null!; + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/OtherFeesCharges.cs b/OpenApiService/Models/Responses/CreditOrganization/OtherFeesCharges.cs new file mode 100644 index 0000000..f9b0981 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OtherFeesCharges.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class OtherFeesCharges + { + [Required] + public string TariffName { get; set; } + public List FeeChargeDetail { get; set; } + public List FeeChargeCap { get; set; } + public List Comments { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/Overdraft.cs b/OpenApiService/Models/Responses/CreditOrganization/Overdraft.cs new file mode 100644 index 0000000..c2e06b9 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Overdraft.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class Overdraft + { + public List Comments { get; set; } + public List OverdraftTierBandSet { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeCap.cs b/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeCap.cs new file mode 100644 index 0000000..60d9f79 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeCap.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class OverdraftFeeChargeCap + { + public string FeeType { get; set; } + public string MinMaxType { get; set; } + public int FeeCapOccurrence { get; set; } + public string FeeCapAmount { get; set; } + public string CappingPeriod { get; set; } + public List Comments { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeDetail.cs b/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeDetail.cs new file mode 100644 index 0000000..e27cbb7 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeeChargeDetail.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class OverdraftFeeChargeDetail + { + public string FeeType { get; set; } + public OtherFeeType OtherFeeType { get; set; } + public string FeeAmount { get; set; } + public string FeeRate { get; set; } + public string FeeRateType { get; set; } + public OtherFeeRateType OtherFeeRateType { get; set; } + public string ApplicationFrequency { get; set; } + public OtherApplicationFrequency OtherApplicationFrequency { get; set; } + public string CalculationFrequency { get; set; } + public OtherCalculationFrequency OtherCalculationFrequency { get; set; } + public string IncrementalBorrowingAmount { get; set; } + public bool NegotiableIndicator { get; set; } + public List Comments { get; set; } + public List FeeChargeCap { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeesCharges.cs b/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeesCharges.cs new file mode 100644 index 0000000..864f2f2 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OverdraftFeesCharges.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class OverdraftFeesCharges + { + public List OverdraftFeeChargeCap { get; set; } + public List OverdraftFeeChargeDetail { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/OverdraftTierBandSet.cs b/OpenApiService/Models/Responses/CreditOrganization/OverdraftTierBandSet.cs new file mode 100644 index 0000000..1a6810a --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/OverdraftTierBandSet.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class OverdraftTierBandSet + { + public string EAR { get; set; } + + public List Comments { get; set; } + + public string Identification { get; set; } + + public string TierCurrency { get; set; } + + public string TierValueMin { get; set; } + + public string TierValueMax { get; set; } + + public int AgreementLengthMin { get; set; } + + public int AgreementLengthMax { get; set; } + + public string AgreementPeriod { get; set; } + + public string OverdraftInterestChargingCoverage { get; set; } + + public bool BankGuaranteedIndicator { get; set; } + + public List OverdraftFeesCharges { get; set; } + + + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/PostalAdress.cs b/OpenApiService/Models/Responses/CreditOrganization/PostalAdress.cs new file mode 100644 index 0000000..2e37fb5 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/PostalAdress.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class PostalAddress + { + public string AddressType { get; set; } = null!; + public List AddressLine { get; set; } = null!; + public string StreetName { get; set; } = null!; + public string BuildingNumber { get; set; } = null!; + public string PostCode { get; set; } = null!; + public string TownName { get; set; } = null!; + public string CountrySubDivision { get; set; } = null!; + public string Country { get; set; } = null!; + + } + +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/Product.cs b/OpenApiService/Models/Responses/CreditOrganization/Product.cs index 5e9c796..520e7ff 100644 --- a/OpenApiService/Models/Responses/CreditOrganization/Product.cs +++ b/OpenApiService/Models/Responses/CreditOrganization/Product.cs @@ -5,21 +5,24 @@ using System.Threading.Tasks; namespace OpenApiService.Models.Responses.CreditOrganization; -public class Product +public class Product { [Required] - public Guid ProductId { get; set; } - + public Guid productId { get; set; } [Required] [StringLength(100)] - public string ProductName { get; set; } = null!; - + public string productName { get; set; } = null!; [Required] - public string ProductType { get; set; } = null!; - + public string productType { get; set; } = null!; [Required] - public string ProductVersion { get; set; } = null!; - + public string productVersion { get; set; } = null!; [Required] - public List Brand { get; set; } = null!; + public Brand Brand { get; set; } = null!; + public ProductDetails? ProductDetails { get; set; } = null!; + public DebitInterest? DebitInterest { get; set; } + public CreditInterest? CreditInterest { get; set; } + public Overdraft? Overdraft { get; set; } + public List? Repayment { get; set; } + public List? OtherFeesCharges { get; set; } + public SupplementaryData? SupplementaryData { get; set; } } diff --git a/OpenApiService/Models/Responses/CreditOrganization/ProductDetails.cs b/OpenApiService/Models/Responses/CreditOrganization/ProductDetails.cs new file mode 100644 index 0000000..953b3e6 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/ProductDetails.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class ProductDetails + { + public bool Active { get; set; } + [DataType(DataType.DateTime)] + public DateTime ActiveFrom { get; set; } + [DataType(DataType.DateTime)] + public DateTime ActiveTo { get; set; } + public int FeeFreeLength { get; set; } + public string FeeFreeLengthPeriod { get; set; } = null!; + public bool ProductInsurance { get; set; } + public List DeliveryRegions { get; set; } + public List FeatureAndBenefit { get; set; } + public List Eligibility { get; set; } + public Insurance Insurance { get; set; } + public List Comments { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/Repayment.cs b/OpenApiService/Models/Responses/CreditOrganization/Repayment.cs new file mode 100644 index 0000000..7ca1507 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/Repayment.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class Repayment + { + public string RepaymentType { get; set; } + public List Comments { get; set; } + public string RepaymentFrequency { get; set; } + public string AmountType { get; set; } + public bool PaymentDate { get; set; } + public OtherRepaymentType OtherRepaymentType { get; set; } + public OtherRepaymentFrequency OtherRepaymentFrequency { get; set; } + public OtherAmountType OtherAmountType { get; set; } + public List RepaymentFeeCharges { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/RepaymentFeeCharges.cs b/OpenApiService/Models/Responses/CreditOrganization/RepaymentFeeCharges.cs new file mode 100644 index 0000000..cd0403e --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/RepaymentFeeCharges.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class RepaymentFeeCharges + { + public List FeeChargeDetail { get; set; } + public List FeeChargeCap { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/SupplementaryData.cs b/OpenApiService/Models/Responses/CreditOrganization/SupplementaryData.cs new file mode 100644 index 0000000..196fbcb --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/SupplementaryData.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class SupplementaryData + { + public Dictionary AdditionalProperties { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/TierBandDeposit.cs b/OpenApiService/Models/Responses/CreditOrganization/TierBandDeposit.cs new file mode 100644 index 0000000..8f1717f --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/TierBandDeposit.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class TierBandDeposit + { + public string AER { get; set; } + + public string RateIncrease { get; set; } + + public string RateDecrease { get; set; } + + public string ProlongationType { get; set; } + + public string MaxAutoprolongation { get; set; } + + public bool Replenishment { get; set; } + + public string ReplenishmentFrequency { get; set; } + + public string MaxAmountDeposit { get; set; } + + public string Restriction { get; set; } + + public string RestrictionType { get; set; } + + public List Comments { get; set; } + + public string Identification { get; set; } + + public string TierCurrency { get; set; } + + public string InterestRate { get; set; } + + public string TierValueMinimum { get; set; } + + public string TierValueMaximum { get; set; } + + public string TierPrimaryValueMinimum { get; set; } + + public string TierPrimaryValueMaximum { get; set; } + + public string TierRemainValueMinimum { get; set; } + + public int TierValueMinTerm { get; set; } + + public string MinTermPeriod { get; set; } + + public int TierValueMaxTerm { get; set; } + + public string MaxTermPeriod { get; set; } + + public string NonLowerBalanceValue { get; set; } + + public string NonLowerBalance { get; set; } + + public string ApplicationFrequency { get; set; } + + public List OtherApplicationFrequency { get; set; } + + public string CalculationFrequency { get; set; } + + public List OtherCalculationFrequency { get; set; } + + public List InterestFeesCharges { get; set; } + + + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/TierBandSetDeposit.cs b/OpenApiService/Models/Responses/CreditOrganization/TierBandSetDeposit.cs new file mode 100644 index 0000000..b78afb8 --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/TierBandSetDeposit.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class TierBandSetDeposit + { + public string TierBandMethodDeposit { get; set; } + public string TierBandMethod { get; set; } + public string CalculationMethod { get; set; } + public List OtherCalculationMethod { get; set; } + public string WithdrawInterest { get; set; } + public string CapitalizationIdentification { get; set; } + public string CapitalizationFrequency { get; set; } + public string EarlyTermination { get; set; } + public string Destination { get; set; } + public List Comments { get; set; } + public List TierBandDeposit { get; set; } + public List TierBandSetEligibility { get; set; } + } +} \ No newline at end of file diff --git a/OpenApiService/Models/Responses/CreditOrganization/TierBandSetEligibility.cs b/OpenApiService/Models/Responses/CreditOrganization/TierBandSetEligibility.cs new file mode 100644 index 0000000..930ebaf --- /dev/null +++ b/OpenApiService/Models/Responses/CreditOrganization/TierBandSetEligibility.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenApiService.Models.Responses.CreditOrganization +{ + public class TierBandSetEligibility + { + public string Name { get; set; } + + public string Description { get; set; } + + public string Type { get; set; } + + public List Comments { get; set; } + + public string Amount { get; set; } + + public bool Indicator { get; set; } + + public string Textual { get; set; } + + public string Period { get; set; } + + public List OtherEligibilityType { get; set; } + + + } +} \ No newline at end of file