2025-08-20 10:31:56 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using Kurs.Platform.Entities;
|
|
|
|
|
|
using Kurs.Platform.Services;
|
|
|
|
|
|
using Volo.Abp.Domain.Repositories;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using Kurs.Platform.Data.Seeds;
|
|
|
|
|
|
using Kurs.Sender.Mail;
|
|
|
|
|
|
using Volo.Abp.Settings;
|
|
|
|
|
|
using Kurs.Platform.Demos;
|
|
|
|
|
|
using Kurs.Platform.Blog;
|
|
|
|
|
|
using Volo.Abp.Domain.Entities;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using Volo.Abp.Application.Dtos;
|
|
|
|
|
|
using Kurs.Platform.Orders;
|
|
|
|
|
|
using System.Text.Json;
|
2025-08-21 11:41:59 +00:00
|
|
|
|
using Kurs.Platform.Abouts;
|
|
|
|
|
|
using Kurs.Platform.Contacts;
|
2025-08-20 10:31:56 +00:00
|
|
|
|
|
|
|
|
|
|
namespace Kurs.Platform.Public;
|
|
|
|
|
|
|
|
|
|
|
|
public class PublicAppService : PlatformAppService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IRepository<Service, Guid> _serviceRepository;
|
|
|
|
|
|
private readonly ISettingProvider _settingProvider;
|
|
|
|
|
|
private readonly IKursEmailSender _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, string> _paymentMethodRepository;
|
2025-08-20 19:26:08 +00:00
|
|
|
|
private readonly IRepository<InstallmentOption> _installmentOptionRepository;
|
2025-08-20 10:31:56 +00:00
|
|
|
|
private readonly IRepository<Order, Guid> _orderRepository;
|
2025-08-21 11:41:59 +00:00
|
|
|
|
private readonly IRepository<About, Guid> _aboutRepository;
|
|
|
|
|
|
private readonly IRepository<Contact, Guid> _contactRepository;
|
2025-08-20 10:31:56 +00:00
|
|
|
|
|
|
|
|
|
|
public PublicAppService(
|
|
|
|
|
|
IRepository<Service, Guid> serviceRepository,
|
|
|
|
|
|
ISettingProvider settingProvider,
|
|
|
|
|
|
IKursEmailSender emailSender,
|
|
|
|
|
|
IRepository<Demo, Guid> demoRepository,
|
|
|
|
|
|
IRepository<BlogPost, Guid> postRepository,
|
|
|
|
|
|
IRepository<BlogCategory, Guid> categoryRepository,
|
|
|
|
|
|
IRepository<Product, Guid> productRepository,
|
|
|
|
|
|
IRepository<PaymentMethod, string> paymentMethodRepository,
|
2025-08-20 19:26:08 +00:00
|
|
|
|
IRepository<InstallmentOption> installmentOptionRepository,
|
2025-08-21 11:41:59 +00:00
|
|
|
|
IRepository<Order, Guid> orderRepository,
|
|
|
|
|
|
IRepository<About, Guid> aboutRepository,
|
|
|
|
|
|
IRepository<Contact, Guid> contactRepository
|
2025-08-20 10:31:56 +00:00
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
_serviceRepository = serviceRepository;
|
|
|
|
|
|
_settingProvider = settingProvider;
|
|
|
|
|
|
_emailSender = emailSender;
|
|
|
|
|
|
_demoRepository = demoRepository;
|
|
|
|
|
|
_postRepository = postRepository;
|
|
|
|
|
|
_categoryRepository = categoryRepository;
|
|
|
|
|
|
_productRepository = productRepository;
|
|
|
|
|
|
_paymentMethodRepository = paymentMethodRepository;
|
|
|
|
|
|
_installmentOptionRepository = installmentOptionRepository;
|
|
|
|
|
|
_orderRepository = orderRepository;
|
2025-08-21 11:41:59 +00:00
|
|
|
|
_aboutRepository = aboutRepository;
|
|
|
|
|
|
_contactRepository = contactRepository;
|
2025-08-20 10:31:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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.FullName}");
|
|
|
|
|
|
bodyBuilder.AppendLine($"E-Posta: {input.Email}");
|
|
|
|
|
|
bodyBuilder.AppendLine($"Telefon: {input.Phone}");
|
|
|
|
|
|
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,
|
|
|
|
|
|
new KeyValuePair<string, string>(SenderName, SenderEmailAddress),
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dto.Author = new AuthorDto { Id = post.AuthorId, Name = "User" };
|
|
|
|
|
|
return dto;
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
// ----------- KATEGORİLER (PostCount ile) -----------
|
|
|
|
|
|
var allCategories = await _categoryRepository.GetListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
var allPostQuery = await _postRepository.GetQueryableAsync();
|
|
|
|
|
|
var counts = await AsyncExecuter.ToListAsync(
|
|
|
|
|
|
allPostQuery
|
|
|
|
|
|
.Where(p => p.IsPublished)
|
|
|
|
|
|
.GroupBy(p => p.CategoryId)
|
|
|
|
|
|
.Select(g => new { g.Key, Count = g.Count() })
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
var countDict = counts.ToDictionary(x => x.Key, x => x.Count);
|
|
|
|
|
|
|
|
|
|
|
|
var categoryDtos = ObjectMapper.Map<List<BlogCategory>, List<BlogCategoryDto>>(allCategories);
|
|
|
|
|
|
foreach (var dto in categoryDtos)
|
|
|
|
|
|
{
|
|
|
|
|
|
dto.PostCount = countDict.GetOrDefault(dto.Id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new BlogPostAndCategoriesDto
|
|
|
|
|
|
{
|
|
|
|
|
|
Posts = new PagedResultDto<BlogPostListDto>(totalCount, postDtos),
|
|
|
|
|
|
Categories = categoryDtos
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task<BlogPostDto> GetPostAsync(Guid id)
|
|
|
|
|
|
{
|
|
|
|
|
|
var post = await _postRepository.GetAsync(id);
|
|
|
|
|
|
var dto = ObjectMapper.Map<BlogPost, BlogPostDto>(post);
|
|
|
|
|
|
|
|
|
|
|
|
// Get category
|
|
|
|
|
|
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(
|
|
|
|
|
|
await _categoryRepository.GetAsync(post.CategoryId)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Get author info
|
|
|
|
|
|
dto.Author = new AuthorDto
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = post.AuthorId,
|
|
|
|
|
|
Name = "User"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
{
|
|
|
|
|
|
var products = await _productRepository.GetListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
return ObjectMapper.Map<List<Product>, List<ProductDto>>(products.OrderBy(p => p.Order).ToList());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
{
|
|
|
|
|
|
TenantId = input.Tenant.Id,
|
2025-08-23 17:56:54 +00:00
|
|
|
|
OrganizationName = input.Tenant.OrganizationName,
|
2025-08-20 10:31:56 +00:00
|
|
|
|
Founder = input.Tenant.Founder,
|
|
|
|
|
|
VknTckn = input.Tenant.VknTckn,
|
|
|
|
|
|
TaxOffice = input.Tenant.TaxOffice,
|
|
|
|
|
|
Address = input.Tenant.Address,
|
|
|
|
|
|
Address2 = input.Tenant.Address2,
|
|
|
|
|
|
District = input.Tenant.District,
|
|
|
|
|
|
Country = input.Tenant.Country,
|
|
|
|
|
|
City = input.Tenant.City,
|
|
|
|
|
|
PostalCode = input.Tenant.PostalCode,
|
|
|
|
|
|
Phone = input.Tenant.Phone,
|
|
|
|
|
|
Mobile = input.Tenant.Mobile,
|
|
|
|
|
|
Fax = input.Tenant.Fax,
|
|
|
|
|
|
Email = input.Tenant.Email,
|
|
|
|
|
|
Website = input.Tenant.Website,
|
|
|
|
|
|
|
|
|
|
|
|
Subtotal = input.Subtotal,
|
|
|
|
|
|
Commission = input.Commission,
|
|
|
|
|
|
Total = input.Total,
|
|
|
|
|
|
PaymentMethod = input.PaymentMethod,
|
|
|
|
|
|
Installments = input.Installments,
|
|
|
|
|
|
InstallmentName = input.InstallmentName,
|
|
|
|
|
|
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,
|
|
|
|
|
|
PaymentMethod = entity.PaymentMethod
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-08-21 11:41:59 +00:00
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2025-08-20 10:31:56 +00:00
|
|
|
|
}
|