using System; using System.Collections.Generic; using System.Threading.Tasks; using Sozsoft.Platform.Entities; using Volo.Abp.Domain.Repositories; using System.Text; using Sozsoft.Platform.Data.Seeds; using Sozsoft.Sender.Mail; using Volo.Abp.Settings; using Sozsoft.Platform.Demos; using Volo.Abp.Domain.Entities; using System.Linq; using Volo.Abp.Application.Dtos; using System.Text.Json; using Volo.Abp.Identity; using Sozsoft.Platform.Identity.Dto; namespace Sozsoft.Platform.Public; public class PublicAppService : PlatformAppService { private readonly IRepository _serviceRepository; private readonly ISettingProvider _settingProvider; private readonly ISozsoftEmailSender _emailSender; private readonly IRepository _demoRepository; private readonly IRepository _postRepository; private readonly IRepository _categoryRepository; private readonly IRepository _productRepository; private readonly IRepository _paymentMethodRepository; private readonly IRepository _installmentOptionRepository; private readonly IRepository _orderRepository; private readonly IRepository _aboutRepository; private readonly IRepository _contactRepository; private readonly IIdentityUserRepository _identityUserRepository; public PublicAppService( IRepository serviceRepository, ISettingProvider settingProvider, ISozsoftEmailSender emailSender, IRepository demoRepository, IRepository postRepository, IRepository categoryRepository, IRepository productRepository, IRepository paymentMethodRepository, IRepository installmentOptionRepository, IRepository orderRepository, IRepository aboutRepository, IRepository contactRepository, IIdentityUserRepository identityUserRepository ) { _serviceRepository = serviceRepository; _settingProvider = settingProvider; _emailSender = emailSender; _demoRepository = demoRepository; _postRepository = postRepository; _categoryRepository = categoryRepository; _productRepository = productRepository; _paymentMethodRepository = paymentMethodRepository; _installmentOptionRepository = installmentOptionRepository; _orderRepository = orderRepository; _aboutRepository = aboutRepository; _contactRepository = contactRepository; _identityUserRepository = identityUserRepository; } public async Task> GetServicesListAsync() { var entity = await _serviceRepository.GetListAsync(); return ObjectMapper.Map, List>(entity); } public async Task CreateDemoAsync(DemoDto input) { var demo = ObjectMapper.Map(input); await _demoRepository.InsertAsync(demo); var bodyBuilder = new StringBuilder(); bodyBuilder.AppendLine($"Şirket: {input.OrganizationName}"); bodyBuilder.AppendLine($"Ad Soyad: {input.Name}"); bodyBuilder.AppendLine($"E-Posta: {input.Email}"); bodyBuilder.AppendLine($"Telefon: {input.PhoneNumber}"); bodyBuilder.AppendLine($"Adres: {input.Address}"); bodyBuilder.AppendLine($"Şube Sayısı: {input.NumberOfBranches}"); bodyBuilder.AppendLine($"Kullanıcı Sayısı: {input.NumberOfUsers}"); bodyBuilder.AppendLine($"Mesaj: {input.Message}"); var SenderName = await _settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName); var SenderEmailAddress = await _settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromAddress); await _emailSender.QueueEmailAsync( SenderEmailAddress ?? string.Empty, new KeyValuePair(SenderName ?? string.Empty, SenderEmailAddress ?? string.Empty), null, bodyBuilder.ToString(), subject: PlatformConsts.AppName + " : Demo Talebi"); } public async Task GetPostListAsync(GetBlogPostsInput input) { // IQueryable var postQuery = await _postRepository.GetQueryableAsync(); // 🔎 Arama if (!input.Search.IsNullOrWhiteSpace()) { postQuery = postQuery.Where(p => p.ContentTr.Contains(input.Search) || p.ContentEn.Contains(input.Search)); } // 📁 Kategori filtresi if (input.CategoryId.HasValue) { postQuery = postQuery.Where(p => p.CategoryId == input.CategoryId.Value); } // Toplam adet (sayfalama öncesi) var totalCount = await AsyncExecuter.CountAsync(postQuery); // Sayfalama + sıralama var pagedPosts = await AsyncExecuter.ToListAsync( postQuery .OrderByDescending(p => p.CreationTime) .PageBy(input) ); // Sayfadaki kategori kayıtları var categoryIds = pagedPosts.Select(x => x.CategoryId).Distinct().ToList(); var pageCategories = await _categoryRepository.GetListAsync(x => categoryIds.Contains(x.Id)); var categoryDict = pageCategories.ToDictionary(x => x.Id, x => x); var userIds = pagedPosts.Select(x => x.UserId).Distinct().ToList(); var pageEmployees = await _identityUserRepository.GetListByIdsAsync(userIds); var employeeDict = pageEmployees.ToDictionary(x => x.Id, x => x); // Post DTO mapping var postDtos = pagedPosts.Select(post => { var dto = ObjectMapper.Map(post); if (categoryDict.TryGetValue(post.CategoryId, out var c)) { dto.Category = ObjectMapper.Map(c); } if (employeeDict.TryGetValue(post.UserId, out var e)) { dto.User = ObjectMapper.Map(e); } return dto; }).ToList(); // ----------- KATEGORİLER (PostCount ile) - Optimize edildi ----------- var categoryQueryable = await _categoryRepository.GetQueryableAsync(); var postQueryableForCount = await _postRepository.GetQueryableAsync(); // Kategori listesi ve post sayıları tek sorguda var categoriesWithCounts = await AsyncExecuter.ToListAsync( from category in categoryQueryable join post in postQueryableForCount.Where(p => p.IsPublished) on category.Id equals post.CategoryId into postGroup select new { Category = category, PostCount = postGroup.Count() } ); var categoryDtos = categoriesWithCounts.Select(x => { var dto = ObjectMapper.Map(x.Category); dto.PostCount = x.PostCount; return dto; }).ToList(); return new BlogPostAndCategoriesDto { Posts = new PagedResultDto(totalCount, postDtos), Categories = categoryDtos }; } private async Task GetPostAsync(Guid id) { // Tek sorguda post ve category'yi çek (N+1 önleme) var queryable = await _postRepository.GetQueryableAsync(); var categoryQueryable = await _categoryRepository.GetQueryableAsync(); var result = await AsyncExecuter.FirstOrDefaultAsync( from post in queryable.Where(p => p.Id == id) join category in categoryQueryable on post.CategoryId equals category.Id select new { Post = post, Category = category } ); if (result == null) throw new EntityNotFoundException(typeof(BlogPost)); var dto = ObjectMapper.Map(result.Post); dto.Category = ObjectMapper.Map(result.Category); return dto; } public async Task GetPostBySlugAsync(string slug) { var post = await _postRepository.FirstOrDefaultAsync(x => x.Slug == slug); if (post == null) { throw new EntityNotFoundException(typeof(BlogPost)); } return await GetPostAsync(post.Id); } public async Task> GetProductListAsync() { // Performans: Sıralamayı database'de yap var queryable = await _productRepository.GetQueryableAsync(); var products = await AsyncExecuter.ToListAsync( queryable.OrderBy(p => p.Order) ); return ObjectMapper.Map, List>(products); } public async Task> GetPaymentMethodListAsync() { var paymentMethods = await _paymentMethodRepository.GetListAsync(); return ObjectMapper.Map, List>(paymentMethods); } public async Task> GetInstallmentOptionListAsync() { var installmentOptions = await _installmentOptionRepository.GetListAsync(); return ObjectMapper.Map, List>(installmentOptions); } public async Task CreateOrderAsync(OrderDto input) { var entity = new Order() { Name = input.Tenant.Name, IsActive = input.Tenant.IsActive, OrganizationName = input.Tenant.OrganizationName, Founder = input.Tenant.Founder, VknTckn = input.Tenant.VknTckn, TaxOffice = input.Tenant.TaxOffice, Address1 = input.Tenant.Address1, Address2 = input.Tenant.Address2, District = input.Tenant.District, Country = input.Tenant.Country, City = input.Tenant.City, PostalCode = input.Tenant.PostalCode, MobileNumber = input.Tenant.MobileNumber, PhoneNumber = input.Tenant.PhoneNumber, FaxNumber = input.Tenant.FaxNumber, Email = input.Tenant.Email, Website = input.Tenant.Website, MenuGroup = input.Tenant.MenuGroup, Subtotal = input.Subtotal, Commission = input.Commission, Total = input.Total, PaymentMethodId = input.PaymentMethodId, Installment = input.Installment, PaymentDataJson = JsonSerializer.Serialize(input.PaymentData), }; foreach (var item in input.Items) { entity.Items.Add(new OrderItem { OrderId = entity.Id, Order = entity, ProductId = item.Product.Id, ProductName = item.Product.Name, BillingCycle = item.BillingCycle, Quantity = item.Quantity, TotalPrice = item.TotalPrice }); } await _orderRepository.InsertAsync(entity, autoSave: true); return new OrderDto { Id = entity.Id, Total = entity.Total, PaymentMethodId = entity.PaymentMethodId }; } public async Task GetAboutAsync() { var entity = await _aboutRepository.FirstOrDefaultAsync() ?? throw new EntityNotFoundException(typeof(About)); return ObjectMapper.Map(entity); } public async Task GetContactAsync() { var entity = await _contactRepository.FirstOrDefaultAsync() ?? throw new EntityNotFoundException(typeof(Contact)); return ObjectMapper.Map(entity); } }