171 lines
5.2 KiB
C#
171 lines
5.2 KiB
C#
using MediatR;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using WhatsAppService.API.Application.Commands;
|
|
using WhatsAppService.Domain.AggregatesModel.ConversationAggregate;
|
|
|
|
namespace WhatsAppService.API.Controllers;
|
|
|
|
/// <summary>
|
|
/// EN: Controller for managing conversations.
|
|
/// VI: Controller để quản lý conversations.
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
[Produces("application/json")]
|
|
public class ConversationsController : ControllerBase
|
|
{
|
|
private readonly IMediator _mediator;
|
|
private readonly IConversationRepository _repository;
|
|
private readonly ILogger<ConversationsController> _logger;
|
|
|
|
public ConversationsController(
|
|
IMediator mediator,
|
|
IConversationRepository repository,
|
|
ILogger<ConversationsController> logger)
|
|
{
|
|
_mediator = mediator;
|
|
_repository = repository;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get conversations by shop with pagination.
|
|
/// VI: Lấy conversations theo shop với phân trang.
|
|
/// </summary>
|
|
[HttpGet]
|
|
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
|
|
public async Task<IActionResult> GetConversations(
|
|
[FromQuery] Guid shopId,
|
|
[FromQuery] string? status,
|
|
[FromQuery] int skip = 0,
|
|
[FromQuery] int take = 20)
|
|
{
|
|
ConversationStatus? statusFilter = null;
|
|
if (!string.IsNullOrEmpty(status))
|
|
{
|
|
statusFilter = ConversationStatus.FromName(status);
|
|
}
|
|
|
|
var conversations = await _repository.GetByShopIdAsync(shopId, skip, take, statusFilter);
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
data = conversations.Select(c => new
|
|
{
|
|
id = c.Id,
|
|
customerWaId = c.CustomerWaId,
|
|
status = c.Status.Name,
|
|
assignedAgentId = c.AssignedAgentId,
|
|
lastMessageAt = c.LastMessageAt,
|
|
createdAt = c.CreatedAt,
|
|
expiresAt = c.ExpiresAt,
|
|
messageCount = c.Messages.Count
|
|
})
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get conversation by ID with messages.
|
|
/// VI: Lấy conversation theo ID kèm messages.
|
|
/// </summary>
|
|
[HttpGet("{id:guid}")]
|
|
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
public async Task<IActionResult> GetById(Guid id)
|
|
{
|
|
var conversation = await _repository.GetByIdAsync(id);
|
|
if (conversation == null)
|
|
{
|
|
return NotFound(new { success = false, error = "Conversation not found" });
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
data = new
|
|
{
|
|
id = conversation.Id,
|
|
customerWaId = conversation.CustomerWaId,
|
|
status = conversation.Status.Name,
|
|
assignedAgentId = conversation.AssignedAgentId,
|
|
lastMessageAt = conversation.LastMessageAt,
|
|
createdAt = conversation.CreatedAt,
|
|
expiresAt = conversation.ExpiresAt,
|
|
messages = conversation.Messages.OrderBy(m => m.Timestamp).Select(m => new
|
|
{
|
|
id = m.Id,
|
|
direction = m.Direction,
|
|
contentType = m.Content.Type,
|
|
text = m.Content.Text,
|
|
status = m.Status,
|
|
timestamp = m.Timestamp
|
|
})
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Send a message in conversation.
|
|
/// VI: Gửi tin nhắn trong conversation.
|
|
/// </summary>
|
|
[HttpPost("{id:guid}/messages")]
|
|
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
public async Task<IActionResult> SendMessage(Guid id, [FromBody] SendMessageRequest request)
|
|
{
|
|
var command = new SendMessageCommand(
|
|
id,
|
|
request.Type,
|
|
request.Text,
|
|
request.MediaUrl,
|
|
request.Caption,
|
|
request.Interactive);
|
|
|
|
var result = await _mediator.Send(command);
|
|
|
|
if (!result.Success)
|
|
{
|
|
return BadRequest(new { success = false, error = result.Error });
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
success = true,
|
|
data = new
|
|
{
|
|
messageId = result.MessageId,
|
|
whatsAppMessageId = result.WhatsAppMessageId
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Close a conversation.
|
|
/// VI: Đóng conversation.
|
|
/// </summary>
|
|
[HttpPost("{id:guid}/close")]
|
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
public async Task<IActionResult> Close(Guid id)
|
|
{
|
|
var conversation = await _repository.GetByIdAsync(id);
|
|
if (conversation == null)
|
|
{
|
|
return NotFound(new { success = false, error = "Conversation not found" });
|
|
}
|
|
|
|
conversation.Close();
|
|
await _repository.UnitOfWork.SaveEntitiesAsync();
|
|
|
|
return NoContent();
|
|
}
|
|
}
|
|
|
|
public record SendMessageRequest(
|
|
string Type,
|
|
string? Text,
|
|
string? MediaUrl,
|
|
string? Caption,
|
|
object? Interactive);
|