sozsoft-platform/api/src/Sozsoft.Platform.Application/Public/PublicAppService.cs

304 lines
11 KiB
C#
Raw Normal View History

2026-02-24 20:44:16 +00:00
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;
namespace Sozsoft.Platform.Public;
public class PublicAppService : PlatformAppService
{
private readonly IRepository<Service, Guid> _serviceRepository;
private readonly ISettingProvider _settingProvider;
private readonly ISozsoftEmailSender _emailSender;
private readonly IRepository<Demo, Guid> _demoRepository;
private readonly IRepository<BlogPost, Guid> _postRepository;
private readonly IRepository<BlogCategory, Guid> _categoryRepository;
private readonly IRepository<Product, Guid> _productRepository;
private readonly IRepository<PaymentMethod, Guid> _paymentMethodRepository;
2026-02-24 20:44:16 +00:00
private readonly IRepository<InstallmentOption> _installmentOptionRepository;
private readonly IRepository<Order, Guid> _orderRepository;
private readonly IRepository<About, Guid> _aboutRepository;
private readonly IRepository<Contact, Guid> _contactRepository;
private readonly IIdentityUserRepository _identityUserRepository;
public PublicAppService(
IRepository<Service, Guid> serviceRepository,
ISettingProvider settingProvider,
ISozsoftEmailSender emailSender,
IRepository<Demo, Guid> demoRepository,
IRepository<BlogPost, Guid> postRepository,
IRepository<BlogCategory, Guid> categoryRepository,
IRepository<Product, Guid> productRepository,
IRepository<PaymentMethod, Guid> paymentMethodRepository,
2026-02-24 20:44:16 +00:00
IRepository<InstallmentOption> installmentOptionRepository,
IRepository<Order, Guid> orderRepository,
IRepository<About, Guid> aboutRepository,
IRepository<Contact, Guid> 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<List<ServiceDto>> GetServicesListAsync()
{
var entity = await _serviceRepository.GetListAsync();
return ObjectMapper.Map<List<Service>, List<ServiceDto>>(entity);
}
public async Task CreateDemoAsync(DemoDto input)
{
var demo = ObjectMapper.Map<DemoDto, Demo>(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<string, string>(SenderName ?? string.Empty, SenderEmailAddress ?? string.Empty),
null,
bodyBuilder.ToString(),
subject: PlatformConsts.AppName + " : Demo Talebi");
}
public async Task<BlogPostAndCategoriesDto> 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);
// Post DTO mapping
var postDtos = pagedPosts.Select(post =>
{
var dto = ObjectMapper.Map<BlogPost, BlogPostListDto>(post);
if (categoryDict.TryGetValue(post.CategoryId, out var c))
{
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(c);
}
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<BlogCategory, BlogCategoryDto>(x.Category);
dto.PostCount = x.PostCount;
return dto;
}).ToList();
return new BlogPostAndCategoriesDto
{
Posts = new PagedResultDto<BlogPostListDto>(totalCount, postDtos),
Categories = categoryDtos
};
}
private async Task<BlogPostDto> 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<BlogPost, BlogPostDto>(result.Post);
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(result.Category);
return dto;
}
public async Task<BlogPostDto> 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<List<ProductDto>> 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<Product>, List<ProductDto>>(products);
}
public async Task<List<PaymentMethodDto>> GetPaymentMethodListAsync()
{
var paymentMethods = await _paymentMethodRepository.GetListAsync();
return ObjectMapper.Map<List<PaymentMethod>, List<PaymentMethodDto>>(paymentMethods);
}
public async Task<List<InstallmentOptionDto>> GetInstallmentOptionListAsync()
{
var installmentOptions = await _installmentOptionRepository.GetListAsync();
return ObjectMapper.Map<List<InstallmentOption>, List<InstallmentOptionDto>>(installmentOptions);
}
public async Task<OrderDto> 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<AboutDto> GetAboutAsync()
{
var entity = await _aboutRepository.FirstOrDefaultAsync() ?? throw new EntityNotFoundException(typeof(About));
return ObjectMapper.Map<About, AboutDto>(entity);
}
public async Task<ContactDto> GetContactAsync()
{
var entity = await _contactRepository.FirstOrDefaultAsync() ?? throw new EntityNotFoundException(typeof(Contact));
return ObjectMapper.Map<Contact, ContactDto>(entity);
}
}