feat: enhance GetMessagesQuery to include additional time notes in message retrieval

This commit is contained in:
2026-01-08 15:02:43 +03:30
parent 59891d1199
commit 0772604432

View File

@@ -1,7 +1,6 @@
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application.Modules.TaskChat.DTOs;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Application.Modules.TaskChat.Queries.GetMessages;
@@ -25,6 +24,39 @@ public class GetMessagesQueryHandler : IBaseQueryHandler<GetMessagesQuery, Pagin
_authHelper = authHelper;
}
private List<MessageDto> CreateAdditionalTimeNotes(
IEnumerable<Domain.ProjectAgg.Entities.TaskSectionAdditionalTime> additionalTimes,
Dictionary<long, string> users,
Guid taskId)
{
var notes = new List<MessageDto>();
foreach (var additionalTime in additionalTimes)
{
var addedByUserName = additionalTime.AddedByUserId.HasValue && users.TryGetValue(additionalTime.AddedByUserId.Value, out var user)
? user
: "سیستم";
var noteContent = $"⏱️ زمان اضافی: {additionalTime.Hours.TotalHours.ToString("F2")} ساعت - {(string.IsNullOrWhiteSpace(additionalTime.Reason) ? "بدون علت" : additionalTime.Reason)} - توسط {addedByUserName}";
var noteDto = new MessageDto
{
Id = Guid.NewGuid(),
TaskId = taskId,
SenderUserId = 0,
SenderName = "سیستم",
MessageType = "Note",
TextContent = noteContent,
CreationDate = additionalTime.CreationDate,
IsMine = false
};
notes.Add(noteDto);
}
return notes;
}
public async Task<OperationResult<PaginationResult<MessageDto>>> Handle(GetMessagesQuery request, CancellationToken cancellationToken)
{
var currentUserId = _authHelper.GetCurrentUserId();
@@ -44,36 +76,52 @@ public class GetMessagesQueryHandler : IBaseQueryHandler<GetMessagesQuery, Pagin
.ToListAsync(cancellationToken);
// ✅ گرفتن تمامی کاربران برای نمایش نام کامل فرستنده به جای "کاربر"
// این بخش تمام UserId هایی که در پیام‌ها استفاده شده را جمع‌آوری می‌کند
// و یک Dictionary ایجاد می‌کند که UserId را به FullName نگاشت می‌کند
var senderUserIds = messages.Select(m => m.SenderUserId).Distinct().ToList();
var users = await _context.Users
.Where(u => senderUserIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id, u => u.FullName, cancellationToken);
// ✅ گرفتن تمامی زمان‌های اضافی (Additional Times) برای نمایش به صورت نوت
// در اینجا تمامی TaskSections مربوط به این تسک را می‌گیریم
// و برای هر کدام تمام AdditionalTimes آن را بارگذاری می‌کنیم
var taskSections = await _context.TaskSections
.Where(ts => ts.TaskId == request.TaskId)
.Include(ts => ts.AdditionalTimes)
.ToListAsync(cancellationToken);
// ✅ تمام زمان‌های اضافی را یکجا بگیر و مرتب کن
var allAdditionalTimes = taskSections
.SelectMany(ts => ts.AdditionalTimes)
.OrderBy(at => at.CreationDate)
.ToList();
var messageDtos = new List<MessageDto>();
// ✅ ابتدا زمان‌های اضافی قبل از اولین پیام را اضافه کن (اگر پیامی وجود داشته باشد)
if (messages.Any())
{
var firstMessageDate = messages.First().CreationDate;
var additionalTimesBeforeFirstMessage = allAdditionalTimes
.Where(at => at.CreationDate < firstMessageDate)
.ToList();
messageDtos.AddRange(CreateAdditionalTimeNotes(additionalTimesBeforeFirstMessage, users, request.TaskId));
}
else
{
// ✅ اگر هیچ پیامی وجود ندارد، همه زمان‌های اضافی را نمایش بده
messageDtos.AddRange(CreateAdditionalTimeNotes(allAdditionalTimes, users, request.TaskId));
}
foreach (var message in messages)
{
// ✅ نام فرستنده را از Dictionary Users بگیر، در صورت عدم وجود "کاربر ناشناس" نمایش بده
var senderName = users.ContainsKey(message.SenderUserId)
? users[message.SenderUserId]
: "کاربر ناشناس";
var senderName = users.GetValueOrDefault(message.SenderUserId, "کاربر ناشناس");
var dto = new MessageDto
{
Id = message.Id,
TaskId = message.TaskId,
SenderUserId = message.SenderUserId,
SenderName = senderName, // ✅ از User واقعی استفاده می‌کنیم
SenderName = senderName,
MessageType = message.MessageType.ToString(),
TextContent = message.TextContent,
ReplyToMessageId = message.ReplyToMessageId,
@@ -88,10 +136,7 @@ public class GetMessagesQueryHandler : IBaseQueryHandler<GetMessagesQuery, Pagin
if (message.ReplyToMessage != null)
{
// ✅ برای پیام‌های Reply نیز نام فرستنده را درست نمایش بده
var replySenderName = users.ContainsKey(message.ReplyToMessage.SenderUserId)
? users[message.ReplyToMessage.SenderUserId]
: "کاربر ناشناس";
var replySenderName = users.GetValueOrDefault(message.ReplyToMessage.SenderUserId, "کاربر ناشناس");
dto.ReplyToMessage = new MessageDto
{
@@ -125,55 +170,31 @@ public class GetMessagesQueryHandler : IBaseQueryHandler<GetMessagesQuery, Pagin
messageDtos.Add(dto);
// ✅ اینجا بخش جدید است: نوت‌های زمان اضافی را بین پیام‌ها اضافه کن
// این بخش تمام AdditionalTimes را که بعد از این پیام اضافه شده‌اند را پیدا می‌کند
var additionalTimesAfterMessage = taskSections
.SelectMany(ts => ts.AdditionalTimes)
.Where(at => at.AddedAt > message.CreationDate) // ✅ تغییر به AddedAt (زمان واقعی اضافه شدن)
.OrderBy(at => at.AddedAt)
.FirstOrDefault();
// ✅ پیدا کردن پیام بعدی (اگر وجود داشته باشد)
var currentIndex = messages.IndexOf(message);
var nextMessage = currentIndex < messages.Count - 1 ? messages[currentIndex + 1] : null;
if (additionalTimesAfterMessage != null)
if (nextMessage != null)
{
// ✅ تمام AdditionalTimes بین این پیام و پیام قبلی را بگیر
var additionalTimesByDate = taskSections
.SelectMany(ts => ts.AdditionalTimes)
.Where(at => at.AddedAt <= message.CreationDate &&
(messageDtos.Count == 1 || at.AddedAt > messageDtos[messageDtos.Count - 2].CreationDate))
.OrderBy(at => at.AddedAt)
// ✅ زمان‌های اضافی بین این پیام و پیام بعدی
var additionalTimesBetween = allAdditionalTimes
.Where(at => at.CreationDate > message.CreationDate && at.CreationDate < nextMessage.CreationDate)
.ToList();
foreach (var additionalTime in additionalTimesByDate)
{
// ✅ نام کاربری که این زمان اضافی را اضافه کرد
var addedByUserName = additionalTime.AddedByUserId.HasValue && users.TryGetValue(additionalTime.AddedByUserId.Value, out var user)
? user
: "سیستم";
messageDtos.AddRange(CreateAdditionalTimeNotes(additionalTimesBetween, users, request.TaskId));
}
else
{
// ✅ این آخرین پیام است، زمان‌های اضافی بعد از آن را اضافه کن
var additionalTimesAfterLastMessage = allAdditionalTimes
.Where(at => at.CreationDate > message.CreationDate)
.ToList();
// ✅ محتوای نوت را با اطلاعات کامل ایجاد کن
// نمایش می‌دهد: مقدار زمان + علت + نام کسی که اضافه کرد
var noteContent = $"⏱️ زمان اضافی: {additionalTime.Hours.TotalHours:F2} ساعت - {(string.IsNullOrWhiteSpace(additionalTime.Reason) ? "بدون علت" : additionalTime.Reason)} - توسط {addedByUserName}";
// ✅ نوت را به عنوان MessageDto خاصی ایجاد کن
var noteDto = new MessageDto
{
Id = Guid.NewGuid(),
TaskId = request.TaskId,
SenderUserId = 0, // ✅ سیستم برای نشان دادن اینکه یک پیام خودکار است
SenderName = "سیستم",
MessageType = "Note", // ✅ نوع پیام: Note (یادداشت سیستم)
TextContent = noteContent,
CreationDate = additionalTime.AddedAt, // ✅ تاریخ اضافه شدن زمان اضافی
IsMine = false
};
messageDtos.Add(noteDto);
}
messageDtos.AddRange(CreateAdditionalTimeNotes(additionalTimesAfterLastMessage, users, request.TaskId));
}
}
// ✅ مرتب کردن نهایی تمام پیام‌ها (معمولی + نوت‌ها) بر اساس زمان ایجاد
// اینطور که نوت‌های زمان اضافی در جای درست خود قرار می‌گیرند
messageDtos = messageDtos.OrderBy(m => m.CreationDate).ToList();
var response = new PaginationResult<MessageDto>()