10.
Implementation A partner, not just software HexDive Technologies' local team handles setup, data migration, training and ongoing support — in Sinhala, Tamil and English. [confirm] 1 Discovery Map your network, products and processes. 2 Configuration Set up depots, pricing, schemes, routes and users. 3 Migration & training Move your data and train every team. 4 Go-live & support Dedicated account manager and local support desk.
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Expense;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/expenses")]
|
||||
public class ExpenseController(
|
||||
ExpenseService service,
|
||||
IPermissionService permissions,
|
||||
ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
private async Task<bool> HasAsync(string code)
|
||||
{
|
||||
if (currentUser.RoleId is not { } roleId) return false;
|
||||
return await permissions.HasPermissionAsync(roleId, code);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize("expense.view")]
|
||||
public async Task<IActionResult> List(
|
||||
[FromQuery] ExpenseStatus? status,
|
||||
[FromQuery] Guid? categoryId,
|
||||
[FromQuery] Guid? warehouseId,
|
||||
[FromQuery] DateTime? from,
|
||||
[FromQuery] DateTime? to,
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 20) =>
|
||||
Ok(await service.ListAsync(status, categoryId, warehouseId, from, to, page, pageSize));
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize("expense.view")]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
{
|
||||
var result = await service.GetAsync(id);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create endpoint takes a required ?action= query to drive the 4 form buttons:
|
||||
/// draft → Save draft; post → Save & post (requires expense.post); pay → Save & pay
|
||||
/// (requires expense.post + expense.pay). Draft is the default.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Authorize("expense.create")]
|
||||
public async Task<IActionResult> Create(
|
||||
CreateExpenseRequest request,
|
||||
[FromQuery] ExpenseAction action = ExpenseAction.Draft,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (action is ExpenseAction.Post or ExpenseAction.Pay && !await HasAsync("expense.post"))
|
||||
return Forbid();
|
||||
if (action == ExpenseAction.Pay && !await HasAsync("expense.pay"))
|
||||
return Forbid();
|
||||
|
||||
try { return Ok(await service.CreateAsync(request, action, ct)); }
|
||||
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize("expense.create")]
|
||||
public async Task<IActionResult> UpdateDraft(Guid id, UpdateExpenseDraftRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await service.UpdateDraftAsync(id, request, ct);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/post")]
|
||||
[Authorize("expense.post")]
|
||||
public async Task<IActionResult> Post(Guid id, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await service.PostAsync(id, ct);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/pay")]
|
||||
[Authorize("expense.pay")]
|
||||
public async Task<IActionResult> Pay(Guid id, ExpensePaymentRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await service.PayAsync(id, request, ct);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/void")]
|
||||
[Authorize("expense.void")]
|
||||
public async Task<IActionResult> Void(Guid id, VoidExpenseRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await service.VoidAsync(id, request?.Reason, ct);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user