diff --git a/.version b/.version index cea20cc..1c6f6f4 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -0.22.24.42 \ No newline at end of file +0.22.25.43 \ No newline at end of file diff --git a/Netina.Api/Controller/SeedController.cs b/Netina.Api/Controller/SeedController.cs index 13fe785..045a2c1 100644 --- a/Netina.Api/Controller/SeedController.cs +++ b/Netina.Api/Controller/SeedController.cs @@ -3,28 +3,48 @@ using Netina.Common.Models.Exception; using Netina.Domain.CommandQueries.Commands; using Netina.Domain.Dtos.RequestDtos.SeedDtos; using Netina.Domain.Dtos.SmallDtos; +using Netina.Domain.Entities.Blogs; +using Netina.Repository.Repositories.Base; namespace Netina.Api.Controller; public class SeedController : ICarterModule { + private readonly IWebHostEnvironment _environment; + + public SeedController(IWebHostEnvironment environment) + { + _environment = environment; + } public void AddRoutes(IEndpointRouteBuilder app) { - //var group = app.NewVersionedApi("Seed") - // .MapGroup("api/seed"); + if (_environment.IsDevelopment()) + { + var group = app.NewVersionedApi("Seed") + .MapGroup("api/seed"); - //group.MapPost("categories", SeedCategoriesAsync) - // .WithDisplayName("SeedCategoriesAsync") - // .HasApiVersion(1.0); + group.MapPost("product/categories", SeedCategoriesAsync) + .WithDisplayName("SeedCategoriesAsync") + .HasApiVersion(1.0); - //group.MapPost("brands", SeedBrandsAsync) - // .WithDisplayName("SeedBrandsAsync") - // .HasApiVersion(1.0); + group.MapPost("product/brands", SeedBrandsAsync) + .WithDisplayName("SeedBrandsAsync") + .HasApiVersion(1.0); + + group.MapPost("products", SeedProductsAsync) + .WithDisplayName("SeedProductsAsync") + .HasApiVersion(1.0); + + group.MapPost("blogs", SeedBlogsAsync) + .WithDisplayName("SeedBlogsAsync") + .HasApiVersion(1.0); + + group.MapPost("blog/categories", SeedBlogCategoriesAsync) + .WithDisplayName("SeedBlogCategoriesAsync") + .HasApiVersion(1.0); + } - //group.MapPost("products",SeedProductsAsync) - // .WithDisplayName("SeedProductsAsync") - // .HasApiVersion(1.0); } @@ -82,4 +102,41 @@ public class SeedController : ICarterModule return TypedResults.Ok(brands); } + + public async Task SeedBlogsAsync([FromBody] List request, [FromQuery]string key,IRepositoryWrapper repositoryWrapper,CancellationToken cancellationToken) + { + + if (key != "kKAYskyG8xPxKnJrHkuYxub4Ao2bnz7AOmNtwDT0RaqzaG7ZvbvaP29tCrC8wJ823RczJFXOIQT2bDOec4F38A==") + throw new AppException("Key is not valid", ApiResultStatusCode.UnAuthorized); + foreach (var seedBlogRequestDto in request) + { + var ent = Blog.Create(seedBlogRequestDto.Title, seedBlogRequestDto.Content, seedBlogRequestDto.Tags, seedBlogRequestDto.ReadingTime, + seedBlogRequestDto.Summery, seedBlogRequestDto.IsSuggested, seedBlogRequestDto.CategoryId); + repositoryWrapper.SetRepository().Add(ent); + await repositoryWrapper.SaveChangesAsync(cancellationToken); + } + return TypedResults.Ok(); + } + + public async Task SeedBlogCategoriesAsync([FromBody] List request, [FromQuery] string key, [FromServices]IRepositoryWrapper repositoryWrapper, CancellationToken cancellationToken) + { + + if (key != "kKAYskyG8xPxKnJrHkuYxub4Ao2bnz7AOmNtwDT0RaqzaG7ZvbvaP29tCrC8wJ823RczJFXOIQT2bDOec4F38A==") + throw new AppException("Key is not valid", ApiResultStatusCode.UnAuthorized); + + Dictionary categories = new Dictionary(); + var baseCategory = BlogCategory.Create("دسته بندی نشده","دسته بندی برای بلاگ های دسته بندی نشده"); + repositoryWrapper.SetRepository().Add(baseCategory); + await repositoryWrapper.SaveChangesAsync(cancellationToken); + categories.Add(0, baseCategory.Id); + foreach (var requestDto in request) + { + var ent = BlogCategory.Create(requestDto.Name, requestDto.Description); + repositoryWrapper.SetRepository().Add(ent); + await repositoryWrapper.SaveChangesAsync(cancellationToken); + categories.Add(requestDto.BaseCategoryId, ent.Id); + } + + return TypedResults.Ok(categories); + } } \ No newline at end of file diff --git a/Netina.Api/Netina.Api.csproj b/Netina.Api/Netina.Api.csproj index 202b0cd..d734689 100644 --- a/Netina.Api/Netina.Api.csproj +++ b/Netina.Api/Netina.Api.csproj @@ -6,8 +6,8 @@ enable true Linux - 0.22.24.42 - 0.22.24.42 + 0.22.25.43 + 0.22.25.43 diff --git a/Netina.Api/WebFramework/Configurations/ServiceExtensions.cs b/Netina.Api/WebFramework/Configurations/ServiceExtensions.cs index b576416..68f8a24 100644 --- a/Netina.Api/WebFramework/Configurations/ServiceExtensions.cs +++ b/Netina.Api/WebFramework/Configurations/ServiceExtensions.cs @@ -57,7 +57,7 @@ public static class ServiceExtensions serviceCollection.AddDbContextFactory(options => { options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); - options.UseNpgsql(Configuration.GetConnectionString("Postgres"), b => b.MigrationsAssembly("NetinaShop.Repository")) + options.UseNpgsql(Configuration.GetConnectionString("Postgres"), b => b.MigrationsAssembly("Netina.Repository")) .UseProjectAssembly(typeof(ApplicationUser).Assembly); //options.EnableServiceProviderCaching(true); diff --git a/Netina.Core/CoreServices/SettingService.cs b/Netina.Core/CoreServices/SettingService.cs index ec4e8eb..3d41261 100644 --- a/Netina.Core/CoreServices/SettingService.cs +++ b/Netina.Core/CoreServices/SettingService.cs @@ -19,7 +19,7 @@ public class SettingService : ISettingService public async Task GetSettingAsync(string settingName, CancellationToken cancellationToken = default) { - var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"NetinaShop.Domain.MartenEntities.Settings.{settingName}"); + var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"Netina.Domain.MartenEntities.Settings.{settingName}"); if (type == null) throw new AppException("Setting not found", ApiResultStatusCode.NotFound); @@ -39,7 +39,7 @@ public class SettingService : ISettingService public async Task CreateOrUpdateSettingAsync(string settingName, JsonDocument settingObj, CancellationToken cancellationToken = default) { - var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"NetinaShop.Domain.MartenEntities.Settings.{settingName}"); + var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"Netina.Domain.MartenEntities.Settings.{settingName}"); if (type == null) throw new AppException("Setting not found", ApiResultStatusCode.NotFound); @@ -52,7 +52,7 @@ public class SettingService : ISettingService { JsonData = JsonConvert.SerializeObject(settingObj.Deserialize(type)), Name = settingName, - DotnetType = type.FullName ?? $"NetinaShop.Domain.MartenEntities.Settings.{settingName}" + DotnetType = type.FullName ?? $"Netina.Domain.MartenEntities.Settings.{settingName}" }; } else diff --git a/Netina.Domain/Dtos/RequestDtos/SeedDtos/SeedBlogRequestDto.cs b/Netina.Domain/Dtos/RequestDtos/SeedDtos/SeedBlogRequestDto.cs new file mode 100644 index 0000000..d121fdf --- /dev/null +++ b/Netina.Domain/Dtos/RequestDtos/SeedDtos/SeedBlogRequestDto.cs @@ -0,0 +1,19 @@ +namespace Netina.Domain.Dtos.RequestDtos.SeedDtos; + +public class SeedBlogRequestDto +{ + public string Title { get; set; } = string.Empty; + public string Content { get; set; } = string.Empty; + public string Tags { get; set; } = string.Empty; + public int ReadingTime { get; set; } + public string Summery { get; set; } = string.Empty; + public bool IsSuggested { get; set; } + public Guid CategoryId { get; set; } +} + +public class SeedBlogCategoryRequestDto +{ + public int BaseCategoryId { get; set; } + public string Description { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/Netina.Infrastructure/Services/ZarinpalService.cs b/Netina.Infrastructure/Services/ZarinpalService.cs index 0724fba..eed25ed 100644 --- a/Netina.Infrastructure/Services/ZarinpalService.cs +++ b/Netina.Infrastructure/Services/ZarinpalService.cs @@ -73,8 +73,8 @@ public class ZarinpalService : IPaymentService merchant_id = paymentSetting.ZarinPalApiKey }; var response = await _restApiWrapper.ZarinpalRestApi.VerifyPaymentAsync(request); - //if (response.data.code != 100) - // throw new AppException($"Exception in get link from zarinpal | {response.data.message}"); + if (response.data.code != 100) + throw new AppException($"Exception in get link from zarinpal | {response.data.message}"); payment.Status = PaymentStatus.Paid; payment.CardPan = response.data.card_pan; diff --git a/Netina.sln b/Netina.sln index 8454860..e889f89 100644 --- a/Netina.sln +++ b/Netina.sln @@ -23,7 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConfigFiles", "ConfigFiles" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{4B7737FD-3BFC-4C21-AB47-4BFAF1CD1EDA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetinaShop.WordPressDBConverter", "Tools\NetinaShop.WordPressDBConverter\NetinaShop.WordPressDBConverter.csproj", "{5112E6D9-FA93-4CE0-95EE-A5F6B1DD52B6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netina.WordPressDBConverter", "Tools\NetinaShop.WordPressDBConverter\Netina.WordPressDBConverter.csproj", "{5112E6D9-FA93-4CE0-95EE-A5F6B1DD52B6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostDto.cs b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostDto.cs index b1e3953..6215d17 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostDto.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostDto.cs @@ -1,4 +1,4 @@ -namespace NetinaShop.WordPressDBConverter.Models; +namespace Netina.WordPressDBConverter.Models; public class WordPressPostDto { diff --git a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostMetaDto.cs b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostMetaDto.cs index 569cd94..96b1011 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostMetaDto.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostMetaDto.cs @@ -1,4 +1,4 @@ -namespace NetinaShop.WordPressDBConverter.Models; +namespace Netina.WordPressDBConverter.Models; public class WordPressPostMetaDto { diff --git a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostTagDto.cs b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostTagDto.cs new file mode 100644 index 0000000..e7340af --- /dev/null +++ b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressPostTagDto.cs @@ -0,0 +1,8 @@ +namespace Netina.WordPressDBConverter.Models; + +public class WordPressPostTagDto +{ + public int TermId { get; set; } + public string Tag { get; set; } = string.Empty; + public int PostId { get; set; } +} \ No newline at end of file diff --git a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermDto.cs b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermDto.cs index 8dd4318..b4abab9 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermDto.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermDto.cs @@ -1,4 +1,4 @@ -namespace NetinaShop.WordPressDBConverter.Models; +namespace Netina.WordPressDBConverter.Models; public class WordPressTermDto { diff --git a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermRelationDto.cs b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermRelationDto.cs index 6b9fe58..e280cc5 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermRelationDto.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermRelationDto.cs @@ -1,4 +1,4 @@ -namespace NetinaShop.WordPressDBConverter.Models; +namespace Netina.WordPressDBConverter.Models; public class WordPressTermRelationDto { diff --git a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermTaxonomyDto.cs b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermTaxonomyDto.cs index e35fde7..c38845a 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermTaxonomyDto.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Models/WordPressTermTaxonomyDto.cs @@ -1,4 +1,4 @@ -namespace NetinaShop.WordPressDBConverter.Models; +namespace Netina.WordPressDBConverter.Models; public class WordPressTermTaxonomyDto { diff --git a/Tools/NetinaShop.WordPressDBConverter/NetinaShop.WordPressDBConverter.csproj b/Tools/NetinaShop.WordPressDBConverter/Netina.WordPressDBConverter.csproj similarity index 100% rename from Tools/NetinaShop.WordPressDBConverter/NetinaShop.WordPressDBConverter.csproj rename to Tools/NetinaShop.WordPressDBConverter/Netina.WordPressDBConverter.csproj diff --git a/Tools/NetinaShop.WordPressDBConverter/Program.cs b/Tools/NetinaShop.WordPressDBConverter/Program.cs index efffab0..217e0b7 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Program.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Program.cs @@ -1,44 +1,121 @@ -using NetinaShop.WordPressDBConverter.Models; -using NetinaShop.WordPressDBConverter.Services.RestServices; +using Netina.Common.Extensions; +using Netina.Domain.CommandQueries.Commands; +using Netina.Domain.Dtos.RequestDtos.SeedDtos; +using Netina.Domain.Dtos.SmallDtos; +using Netina.WordPressDBConverter.Models; +using Netina.WordPressDBConverter.Services.RestServices; using Newtonsoft.Json; -Console.ReadKey(); +var termReader = new StreamReader("F:\\wp_terms.json"); +var termJson = termReader.ReadToEnd(); +Console.WriteLine("Terms File Read Success !"); +var terms = JsonConvert.DeserializeObject>(termJson); +if (terms == null) + throw new Exception("Terms is null"); + +var termTaxonomyReader = new StreamReader("F:\\wp_term_taxonomy.json"); +var termTaxonomyJson = termTaxonomyReader.ReadToEnd(); +Console.WriteLine("Term Taxonomy File Read Success !"); +var termTaxonomies = JsonConvert.DeserializeObject>(termTaxonomyJson); +if (termTaxonomies == null) + throw new Exception("Term Taxonomies is null"); + + +var termRelationshipsReader = new StreamReader("F:\\wp_term_relationships.json"); +var termRelationshipsJson = termRelationshipsReader.ReadToEnd(); +Console.WriteLine("Term Relationships File Read Success !"); +var termRelationships = JsonConvert.DeserializeObject>(termRelationshipsJson); +if (termRelationships == null) + throw new Exception("Term Relationships is null"); var postReader = new StreamReader("F:\\wp_posts.json"); -int j = 0; -int i = 0; -while (!postReader.EndOfStream) +var json = postReader.ReadToEnd(); +Console.WriteLine("Post File Read Success !"); +var posts = JsonConvert.DeserializeObject>(json); +if (posts == null) + throw new Exception("Posts is null"); + + +//CREATE CATEGORY PART +List categories = new List(); +List tags = new List(); +foreach (var taxonomy in termTaxonomies) { - var postJson = await postReader.ReadLineAsync(); - if (postJson != null) + if (taxonomy.taxonomy == "category") { - try - { - var post = JsonConvert.DeserializeObject(postJson.Substring(0,postJson.Length-1)); - if (post != null) + var term = terms.FirstOrDefault(t => t.term_id == taxonomy.term_id); + if (term != null) + categories.Add(new SeedBlogCategoryRequestDto { + BaseCategoryId = term.term_id.ToInt(), + Description = taxonomy.description, + Name = term.name + }); + } - if (post.post_type == "page") - { - - Console.WriteLine($"Page number : {j++}"); - } - - if (post.post_type == "post") - { - - Console.WriteLine($"Post number : {i++}"); - } - } - } - catch (Exception e) - { - continue; - } + if (taxonomy.taxonomy == "post_tag") + { + var term = terms.FirstOrDefault(t => t.term_id == taxonomy.term_id); + if (term != null) + tags.Add(new WordPressPostTagDto + { + TermId = term.term_id.ToInt(), + Tag = term.name + }); } } +var categoriesRest = await RestWrapper.Instance.SeedRestApi.SeedBlogCategoriesAsync(categories, "kKAYskyG8xPxKnJrHkuYxub4Ao2bnz7AOmNtwDT0RaqzaG7ZvbvaP29tCrC8wJ823RczJFXOIQT2bDOec4F38A=="); +Console.WriteLine($"{categories.Count} ProductCategory Added Success !"); + + +//CREATE BLOG PART +List blogs = new List(); +var random = new Random(1532); +foreach (var wordPressPostDto in posts.Where(p => p.post_type == "post")) +{ + SeedBlogRequestDto blog; + Guid categoryId = default; + string postTags = string.Empty; + var postTermRelations = termRelationships.Where(p => p.object_id == wordPressPostDto.ID); + foreach (var postTermRelation in postTermRelations) + { + var taxanomy = termTaxonomies.FirstOrDefault(f => f.term_taxonomy_id == postTermRelation.term_taxonomy_id); + if (taxanomy != null) + { + if (taxanomy.taxonomy == "category") + categoryId = categoriesRest.FirstOrDefault(c => c.Key == taxanomy.term_id.ToInt()).Value; + if (taxanomy.taxonomy == "post_tag") + postTags += tags.FirstOrDefault(t => t.TermId == taxanomy.term_id.ToInt())?.Tag + " , "; + } + } + + if (categoryId == default) + categoryId = categoriesRest.FirstOrDefault(c => c.Key == 0).Value; + + + blog = new SeedBlogRequestDto + { + CategoryId = categoryId, + Content = wordPressPostDto.post_content, + IsSuggested = false, + ReadingTime = random.Next(1, 15), + Title = wordPressPostDto.post_title, + }; + + blogs.Add(blog); +} + +for (int i = 0; i < blogs.Count / 50; i++) +{ + await RestWrapper.Instance.SeedRestApi.SeedBlogsAsync(blogs.Skip(i * 50).Take(50).ToList(), + "kKAYskyG8xPxKnJrHkuYxub4Ao2bnz7AOmNtwDT0RaqzaG7ZvbvaP29tCrC8wJ823RczJFXOIQT2bDOec4F38A=="); + + Console.WriteLine($"{i * 50} / {blogs.Count} Product Added Success !"); +} + + Console.ReadKey(); diff --git a/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/ISeedRestApi.cs b/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/ISeedRestApi.cs index a2abcef..5180052 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/ISeedRestApi.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/ISeedRestApi.cs @@ -2,16 +2,23 @@ using Netina.Domain.Dtos.RequestDtos.SeedDtos; using Refit; -namespace NetinaShop.WordPressDBConverter.Services.RestServices; +namespace Netina.WordPressDBConverter.Services.RestServices; public interface ISeedRestApi { - [Post("/categories")] + [Post("/product/categories")] Task> SeedCategoriesAsync([Body] List request, [Query] string key); - [Post("/brands")] + [Post("/product/brands")] Task> SeedBrandsAsync([Body] List request, [Query] string key); [Post("/products")] Task SeedProductsAsync([Body] List request, [Query] string key); + + + [Post("/blog/categories")] + Task> SeedBlogCategoriesAsync([Body] List request, [Query] string key); + + [Post("/blogs")] + Task SeedBlogsAsync([Body] List request, [Query] string key); } \ No newline at end of file diff --git a/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/RestWrapper.cs b/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/RestWrapper.cs index f88b627..0106c2d 100644 --- a/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/RestWrapper.cs +++ b/Tools/NetinaShop.WordPressDBConverter/Services/RestServices/RestWrapper.cs @@ -1,6 +1,6 @@ using Refit; -namespace NetinaShop.WordPressDBConverter.Services.RestServices; +namespace Netina.WordPressDBConverter.Services.RestServices; public class RestWrapper {