209 lines
7 KiB
C#
209 lines
7 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Linq.Dynamic.Core;
|
||
using System.Text.Json;
|
||
using System.Threading.Tasks;
|
||
using Erp.Platform.BlobStoring;
|
||
using Erp.Platform.Entities;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Volo.Abp;
|
||
using Volo.Abp.Application.Dtos;
|
||
using Volo.Abp.Application.Services;
|
||
using Volo.Abp.Domain.Repositories;
|
||
using Volo.Abp.Identity;
|
||
|
||
namespace Erp.Platform.Notes;
|
||
|
||
[Authorize]
|
||
public class NoteAppService : CrudAppService<
|
||
Note,
|
||
NoteDto,
|
||
Guid,
|
||
NoteListRequestDto>
|
||
{
|
||
private readonly IRepository<IdentityUser, Guid> _repositoryUser;
|
||
private readonly BlobManager _blobContainer;
|
||
|
||
public NoteAppService(
|
||
IRepository<Note, Guid> repo,
|
||
IRepository<IdentityUser, Guid> repositoryUser,
|
||
BlobManager blobContainer
|
||
) : base(repo)
|
||
{
|
||
_repositoryUser = repositoryUser;
|
||
_blobContainer = blobContainer;
|
||
|
||
// CreatePolicyName = $"{AppCodes.Listforms.Listform}.Create";
|
||
// UpdatePolicyName = $"{AppCodes.Listforms.Listform}.Update";
|
||
// DeletePolicyName = $"{AppCodes.Listforms.Listform}.Delete";
|
||
|
||
// bool canAccess = await authManager.CanAccess(listFormCode, AuthorizationTypeEnum.Update);
|
||
// if (!canAccess)
|
||
// {
|
||
// throw new UserFriendlyException(L[AppErrorCodes.NoAuth]);
|
||
// }
|
||
}
|
||
|
||
public async Task<NoteFileDto> GetDownloadAsync(string savedFileName)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(savedFileName))
|
||
throw new UserFriendlyException("Dosya adı geçersiz");
|
||
|
||
var stream = await _blobContainer.GetAsync(BlobContainerNames.Note, savedFileName);
|
||
if (stream == null)
|
||
throw new UserFriendlyException("Dosya bulunamadı");
|
||
|
||
// Performans: TÜM notları çekmek yerine sadece bu dosyayı içereni bul
|
||
var queryable = await Repository.GetQueryableAsync();
|
||
var notes = await AsyncExecuter.ToListAsync(
|
||
queryable.Where(a => a.FilesJson.Contains(savedFileName))
|
||
);
|
||
|
||
var fileDto = notes
|
||
.SelectMany(a => JsonSerializer.Deserialize<List<NoteFileDto>>(a.FilesJson ?? "[]"))
|
||
.FirstOrDefault(f => f.SavedFileName == savedFileName);
|
||
|
||
using var ms = new MemoryStream();
|
||
await stream.CopyToAsync(ms);
|
||
var bytes = ms.ToArray();
|
||
|
||
// Base64 olarak encode ediyoruz
|
||
return new NoteFileDto
|
||
{
|
||
FileName = fileDto?.FileName ?? savedFileName,
|
||
FileType = fileDto?.FileType ?? "application/octet-stream",
|
||
FileBase64 = Convert.ToBase64String(bytes) // <-- byte[] yerine Base64 string
|
||
};
|
||
}
|
||
|
||
public override async Task<PagedResultDto<NoteDto>> GetListAsync(NoteListRequestDto input)
|
||
{
|
||
// 1️⃣ Filtreleme
|
||
var query = await Repository.GetQueryableAsync();
|
||
|
||
if (!string.IsNullOrWhiteSpace(input.EntityName))
|
||
query = query.Where(a => a.EntityName == input.EntityName);
|
||
|
||
if (!string.IsNullOrWhiteSpace(input.EntityId))
|
||
query = query.Where(a => a.EntityId == input.EntityId);
|
||
|
||
// 2️⃣ Sıralama (database'de)
|
||
if (!string.IsNullOrWhiteSpace(input.Sorting))
|
||
query = query.OrderBy(input.Sorting);
|
||
else
|
||
query = query.OrderByDescending(a => a.CreationTime);
|
||
|
||
// 3️⃣ Toplam sayı (sayfalama öncesi)
|
||
var totalCount = await AsyncExecuter.CountAsync(query);
|
||
|
||
// 4️⃣ Paging
|
||
var activities = await AsyncExecuter.ToListAsync(
|
||
query.Skip(input.SkipCount).Take(input.MaxResultCount)
|
||
);
|
||
|
||
// 5️⃣ Kullanıcı bilgilerini Dictionary ile al (N+1 önleme)
|
||
var userIds = activities.Where(a => a.CreatorId.HasValue)
|
||
.Select(a => a.CreatorId!.Value)
|
||
.Distinct()
|
||
.ToList();
|
||
|
||
var userDict = new Dictionary<Guid, string>();
|
||
if (userIds.Any())
|
||
{
|
||
var userQueryable = await _repositoryUser.GetQueryableAsync();
|
||
var users = await AsyncExecuter.ToListAsync(
|
||
userQueryable.Where(u => userIds.Contains(u.Id))
|
||
.Select(u => new { u.Id, u.UserName })
|
||
);
|
||
userDict = users.ToDictionary(u => u.Id, u => u.UserName);
|
||
}
|
||
|
||
// 6️⃣ DTO mapping - Dictionary lookup ile hızlı
|
||
var noteDtos = activities.Select(a =>
|
||
{
|
||
var dto = ObjectMapper.Map<Note, NoteDto>(a);
|
||
dto.CreateUserName = a.CreatorId.HasValue && userDict.TryGetValue(a.CreatorId.Value, out var userName)
|
||
? userName
|
||
: "Unknown";
|
||
return dto;
|
||
}).ToList();
|
||
|
||
// 7️⃣ Sonuç dön
|
||
return new PagedResultDto<NoteDto>(totalCount, noteDtos);
|
||
}
|
||
|
||
|
||
public override async Task<NoteDto> CreateAsync([FromForm] NoteDto input)
|
||
{
|
||
var fileDtos = new List<NoteFileDto>();
|
||
|
||
if (input.Files != null && input.Files.Length > 0)
|
||
{
|
||
foreach (var file in input.Files)
|
||
{
|
||
await using var stream = file.GetStream();
|
||
var savedFileName = $"{Guid.NewGuid()}_{file.FileName}";
|
||
|
||
await _blobContainer.SaveAsync(
|
||
BlobContainerNames.Note,
|
||
savedFileName,
|
||
stream,
|
||
true
|
||
);
|
||
|
||
// Dosya bilgisini DTO olarak ekle
|
||
fileDtos.Add(new NoteFileDto
|
||
{
|
||
FileName = file.FileName,
|
||
FileType = file.ContentType,
|
||
FileSize = file.ContentLength ?? 0,
|
||
SavedFileName = savedFileName
|
||
});
|
||
}
|
||
}
|
||
|
||
input.FilesJson = JsonSerializer.Serialize(fileDtos);
|
||
|
||
var dto = await base.CreateAsync(input);
|
||
|
||
dto.CreateUserName = CurrentUser.UserName;
|
||
|
||
return dto;
|
||
}
|
||
|
||
public override async Task DeleteAsync(Guid id)
|
||
{
|
||
// Önce entity'i alıyoruz
|
||
var note = await Repository.GetAsync(id);
|
||
|
||
// if (!string.IsNullOrEmpty(note.FilesJson))
|
||
// {
|
||
// try
|
||
// {
|
||
// // FilesJson içindeki dosya bilgilerini deserialize ediyoruz
|
||
// var files = JsonSerializer.Deserialize<List<NoteFileDto>>(note.FilesJson);
|
||
|
||
// if (files != null)
|
||
// {
|
||
// foreach (var file in files)
|
||
// {
|
||
// // Blob storage'dan sil
|
||
// await _noteBlobContainer.DeleteAsync(file.SavedFileName, cancellationToken: default);
|
||
// }
|
||
// }
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// // Opsiyonel: silme sırasında hata loglayabilirsin
|
||
// Logger.LogWarning(ex, "Blob dosyaları silinirken hata oluştu.");
|
||
// }
|
||
// }
|
||
|
||
// Sonra veritabanındaki kaydı sil
|
||
await base.DeleteAsync(id);
|
||
}
|
||
}
|
||
|