101 lines
4.2 KiB
C#

using Marco.Pms.Model.Dtos.Expenses;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Helpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Marco.Pms.Services.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ExpenseController : ControllerBase
{
private readonly UserHelper _userHelper;
private readonly IExpensesService _expensesService;
private readonly ISignalRService _signalR;
private readonly Guid tenantId;
public ExpenseController(
UserHelper userHelper,
IExpensesService expensesService,
ISignalRService signalR
)
{
_userHelper = userHelper;
_expensesService = expensesService;
_signalR = signalR;
tenantId = userHelper.GetTenantId();
}
/// <summary>
/// Retrieves a paginated list of expenses based on user permissions and optional filters.
/// </summary>
/// <param name="filter">A URL-encoded JSON string containing filter criteria. See <see cref="ExpensesFilter"/>.</param>
/// <param name="pageSize">The number of records to return per page.</param>
/// <param name="pageNumber">The page number to retrieve.</param>
/// <returns>A paginated list of expenses.</returns>
[HttpGet("list")]
public async Task<IActionResult> GetExpensesList(string? filter, int pageSize = 20, int pageNumber = 1)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.GetExpensesListAsync(loggedInEmployee, tenantId, filter, pageSize, pageNumber);
return StatusCode(response.StatusCode, response);
}
[HttpGet("details/{id}")]
public async Task<IActionResult> GetExpenseDetails(Guid id)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.GetExpenseDetailsAsync(id, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
/// <summary>
/// Creates a new expense entry along with its bill attachments.
/// This operation is transactional and performs validations and file uploads concurrently for optimal performance
/// by leveraging async/await without unnecessary thread-pool switching via Task.Run.
/// </summary>
/// <param name="dto">The data transfer object containing expense details and attachments.</param>
/// <returns>An IActionResult indicating the result of the creation operation.</returns>
[HttpPost("create")]
public async Task<IActionResult> CreateExpense([FromBody] CreateExpensesDto model)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.CreateExpenseAsync(model, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPost("action")]
public async Task<IActionResult> ChangeStatus([FromBody] ExpenseRecordDto model)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.ChangeStatusAsync(model, loggedInEmployee, tenantId);
if (response.Success)
{
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Expanse", Response = response.Data };
await _signalR.SendNotificationAsync(notification);
}
return StatusCode(response.StatusCode, response);
}
[HttpPut("edit/{id}")]
public async Task<IActionResult> UpdateExpanse(Guid id, [FromBody] UpdateExpensesDto model)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.UpdateExpanseAsync(id, model, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpDelete("delete/{id}")]
public void Delete(int id)
{
}
}
}