Files

111 lines
4.8 KiB
C#

using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Stock;
[ApiController]
[Route("api/stock")]
public class StockController(StockService service, ICurrentUserService currentUser) : ControllerBase
{
// ── Query ──────────────────────────────────────────────────────────────
[HttpGet("balances")]
public async Task<IActionResult> GetBalances(
[FromQuery] Guid? locationId,
[FromQuery] LocationType? locationType,
[FromQuery] Guid? itemId,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20)
{
var result = await service.GetBalancesAsync(locationId, locationType, itemId, page, pageSize);
return Ok(result);
}
[HttpGet("balances/{itemId}/total")]
public async Task<IActionResult> GetItemTotal(Guid itemId)
{
var result = await service.GetItemTotalAsync(itemId);
if (result is null) return NotFound();
return Ok(result);
}
[HttpGet("movements")]
public async Task<IActionResult> GetMovements(
[FromQuery] Guid? locationId,
[FromQuery] Guid? itemId,
[FromQuery] MovementType? type,
[FromQuery] DateTime? from,
[FromQuery] DateTime? to,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20)
{
var result = await service.GetMovementsAsync(locationId, itemId, type, from, to, page, pageSize);
return Ok(result);
}
// ── Write ──────────────────────────────────────────────────────────────
[HttpPost("transfer")]
public async Task<IActionResult> Transfer(TransferRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.TransferAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPost("damage")]
public async Task<IActionResult> RecordDamage(DamageRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.RecordDamageAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPost("customer-return")]
public async Task<IActionResult> RecordCustomerReturn(CustomerReturnRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.RecordCustomerReturnAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPost("adjustment")]
public async Task<IActionResult> Adjust(AdjustmentRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
// (testbug.md #28) — fall back to the explicitly supplied user until that's fixed.
var userId = currentUser.UserId ?? request.AdjustedByUserId;
if (userId is null) return BadRequest(new { error = "AdjustedByUserId is required while auth is unavailable" });
try
{
var result = await service.AdjustAsync(request, userId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPatch("movements/{id}/reason")]
public async Task<IActionResult> UpdateMovementReason(Guid id, UpdateMovementReasonRequest request, CancellationToken ct)
{
try
{
var result = await service.UpdateMovementReasonAsync(id, request, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
}