215 lines
9.3 KiB
C#
215 lines
9.3 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.Filters;
|
|
using MiGu.Server.Wms;
|
|
|
|
namespace MiGu.Server.Controllers;
|
|
|
|
[ApiController]
|
|
[Authorize]
|
|
[TypeFilter(typeof(WmsExceptionFilter))]
|
|
[Route("api/wms")]
|
|
public sealed class WmsController : ControllerBase
|
|
{
|
|
private readonly WmsService _service;
|
|
private readonly WmsTransportRuleService _transportRules;
|
|
private readonly WmsTransportTaskService _transportTasks;
|
|
|
|
public WmsController(WmsService service, WmsTransportRuleService transportRules, WmsTransportTaskService transportTasks)
|
|
{
|
|
_service = service;
|
|
_transportRules = transportRules;
|
|
_transportTasks = transportTasks;
|
|
}
|
|
|
|
[HttpGet("areas")]
|
|
public Task<List<WarehouseArea>> Areas([FromQuery] string? q) => _service.Areas(q);
|
|
|
|
[HttpPost("areas")]
|
|
public async Task<IActionResult> SaveArea([FromBody] MasterDataRequest req) => Ok(await _service.SaveArea(req, User.ActorName()));
|
|
|
|
[HttpPut("areas/{id:guid}")]
|
|
public async Task<IActionResult> UpdateArea(Guid id, [FromBody] MasterDataRequest req) =>
|
|
Ok(await _service.SaveArea(req with { Id = id }, User.ActorName()));
|
|
|
|
[HttpDelete("areas/{id:guid}")]
|
|
public async Task<IActionResult> DeleteArea(Guid id, [FromQuery] long? version)
|
|
{
|
|
await _service.DeleteEntity<WarehouseArea>(id, version, User.ActorName());
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("storages")]
|
|
public Task<List<Storage>> Storages([FromQuery] string? q) => _service.Storages(q);
|
|
|
|
[HttpPost("storages")]
|
|
public async Task<IActionResult> SaveStorage([FromBody] StorageRequest req) => Ok(await _service.SaveStorage(req, User.ActorName()));
|
|
|
|
[HttpPut("storages/{id:guid}")]
|
|
public async Task<IActionResult> UpdateStorage(Guid id, [FromBody] StorageRequest req) =>
|
|
Ok(await _service.SaveStorage(req with { Id = id }, User.ActorName()));
|
|
|
|
[HttpDelete("storages/{id:guid}")]
|
|
public async Task<IActionResult> DeleteStorage(Guid id, [FromQuery] long? version)
|
|
{
|
|
await _service.DeleteEntity<Storage>(id, version, User.ActorName());
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("containers")]
|
|
public Task<List<Container>> Containers([FromQuery] string? q) => _service.Containers(q);
|
|
|
|
[HttpPost("containers")]
|
|
public async Task<IActionResult> SaveContainer([FromBody] MasterDataRequest req) => Ok(await _service.SaveContainer(req, User.ActorName()));
|
|
|
|
[HttpPut("containers/{id:guid}")]
|
|
public async Task<IActionResult> UpdateContainer(Guid id, [FromBody] MasterDataRequest req) =>
|
|
Ok(await _service.SaveContainer(req with { Id = id }, User.ActorName()));
|
|
|
|
[HttpDelete("containers/{id:guid}")]
|
|
public async Task<IActionResult> DeleteContainer(Guid id, [FromQuery] long? version)
|
|
{
|
|
await _service.DeleteEntity<Container>(id, version, User.ActorName());
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("materials")]
|
|
public Task<List<Material>> Materials([FromQuery] string? q) => _service.Materials(q);
|
|
|
|
[HttpPost("materials")]
|
|
public async Task<IActionResult> SaveMaterial([FromBody] MaterialRequest req) => Ok(await _service.SaveMaterial(req, User.ActorName()));
|
|
|
|
[HttpPut("materials/{id:guid}")]
|
|
public async Task<IActionResult> UpdateMaterial(Guid id, [FromBody] MaterialRequest req) =>
|
|
Ok(await _service.SaveMaterial(req with { Id = id }, User.ActorName()));
|
|
|
|
[HttpDelete("materials/{id:guid}")]
|
|
public async Task<IActionResult> DeleteMaterial(Guid id, [FromQuery] long? version)
|
|
{
|
|
await _service.DeleteEntity<Material>(id, version, User.ActorName());
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("container-locations")]
|
|
public Task<List<ContainerLocation>> ContainerLocations([FromQuery] string? locationType, [FromQuery] string? q) =>
|
|
_service.ContainerLocations(locationType, q);
|
|
|
|
[HttpPost("container-locations")]
|
|
public async Task<IActionResult> SaveContainerLocation([FromBody] ContainerLocationRequest req) =>
|
|
Ok(await _service.BindOrTransferLocation(req, User.ActorName()));
|
|
|
|
[HttpPost("container-locations/transfer")]
|
|
public async Task<IActionResult> TransferContainerLocation([FromBody] ContainerLocationRequest req) =>
|
|
Ok(await _service.BindOrTransferLocation(req, User.ActorName()));
|
|
|
|
[HttpDelete("container-locations/{containerId:guid}")]
|
|
public async Task<IActionResult> UnbindContainerLocation(Guid containerId, [FromQuery] string? reason)
|
|
{
|
|
await _service.UnbindLocation(containerId, User.ActorName(), reason ?? "");
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("container-materials")]
|
|
public Task<List<ContainerMaterial>> ContainerMaterials([FromQuery] string? q) => _service.ContainerMaterials(q);
|
|
|
|
[HttpPost("container-materials")]
|
|
public async Task<IActionResult> SaveContainerMaterial([FromBody] ContainerMaterialRequest req) =>
|
|
Ok(await _service.SaveContainerMaterial(req, User.ActorName()));
|
|
|
|
[HttpPut("container-materials/{id:guid}")]
|
|
public async Task<IActionResult> UpdateContainerMaterial(Guid id, [FromBody] ContainerMaterialRequest req) =>
|
|
Ok(await _service.SaveContainerMaterial(req with { Id = id }, User.ActorName()));
|
|
|
|
[HttpDelete("container-materials/{id:guid}")]
|
|
public async Task<IActionResult> UnloadContainerMaterial(Guid id, [FromQuery] string? reason)
|
|
{
|
|
await _service.UnloadMaterial(id, User.ActorName(), reason ?? "");
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("container-location-history")]
|
|
public Task<List<ContainerLocationHistory>> ContainerLocationHistory([FromQuery] Guid? containerId) =>
|
|
_service.LocationHistory(containerId);
|
|
|
|
[HttpGet("container-material-history")]
|
|
public Task<List<ContainerMaterialHistory>> ContainerMaterialHistory([FromQuery] Guid? containerId, [FromQuery] Guid? materialId) =>
|
|
_service.MaterialHistory(containerId, materialId);
|
|
|
|
[HttpGet("transport-rules")]
|
|
public Task<List<WmsTransportRule>> TransportRules([FromQuery] string? triggerType, [FromQuery] string? q) =>
|
|
_transportRules.ListAsync(triggerType, q);
|
|
|
|
[HttpPost("transport-rules")]
|
|
public async Task<IActionResult> SaveTransportRule([FromBody] TransportRuleRequest req) =>
|
|
Ok(await _transportRules.SaveAsync(req, User.ActorName()));
|
|
|
|
[HttpPut("transport-rules/{id:guid}")]
|
|
public async Task<IActionResult> UpdateTransportRule(Guid id, [FromBody] TransportRuleRequest req) =>
|
|
Ok(await _transportRules.SaveAsync(req with { Id = id }, User.ActorName()));
|
|
|
|
[HttpDelete("transport-rules/{id:guid}")]
|
|
public async Task<IActionResult> DeleteTransportRule(Guid id, [FromQuery] long? version)
|
|
{
|
|
await _transportRules.DeleteAsync(id, version, User.ActorName());
|
|
return NoContent();
|
|
}
|
|
|
|
[HttpGet("transport-candidates")]
|
|
public async Task<IActionResult> TransportCandidates([FromQuery] TransportRequestQuery q) =>
|
|
Ok(await _transportTasks.PreviewCandidatesAsync(q.ToRequest()));
|
|
|
|
[HttpPost("transport-tasks/generate")]
|
|
public async Task<IActionResult> GenerateTransportTask([FromBody] TransportRequestQuery q) =>
|
|
Ok(await _transportTasks.GenerateAsync(q.ToRequest(), User.ActorName()));
|
|
|
|
[HttpGet("transport-tasks")]
|
|
public Task<List<WmsTransportTask>> TransportTasks([FromQuery] string? status, [FromQuery] string? triggerType) =>
|
|
_transportTasks.ListAsync(status, triggerType);
|
|
|
|
[HttpPost("transport-tasks/{id:guid}/reserve")]
|
|
public async Task<IActionResult> ReserveTransportTask(Guid id, [FromQuery] string? reason) =>
|
|
Ok(await _transportTasks.ReserveAsync(id, User.ActorName(), reason ?? ""));
|
|
|
|
[HttpPost("transport-tasks/{id:guid}/cancel")]
|
|
public async Task<IActionResult> CancelTransportTask(Guid id, [FromQuery] string? reason) =>
|
|
Ok(await _transportTasks.CancelAsync(id, User.ActorName(), reason ?? ""));
|
|
|
|
[HttpPost("transport-tasks/{id:guid}/complete")]
|
|
public async Task<IActionResult> CompleteTransportTask(Guid id, [FromQuery] string? reason) =>
|
|
Ok(await _transportTasks.CompleteAsync(id, User.ActorName(), reason ?? ""));
|
|
|
|
[HttpPost("transport-tasks/{id:guid}/dispatch")]
|
|
public async Task<IActionResult> DispatchTransportTask(Guid id) =>
|
|
Ok(await _transportTasks.DispatchAsync(id, User.ActorName()));
|
|
}
|
|
|
|
public sealed class WmsExceptionFilter : IExceptionFilter
|
|
{
|
|
public void OnException(ExceptionContext context)
|
|
{
|
|
if (context.Exception is not InvalidOperationException ex) return;
|
|
context.Result = new BadRequestObjectResult(new { message = ex.Message });
|
|
context.ExceptionHandled = true;
|
|
}
|
|
}
|
|
|
|
public sealed class TransportRequestQuery
|
|
{
|
|
public string TriggerType { get; set; } = WmsTransportTriggerTypes.MaterialCall;
|
|
public Guid? RuleId { get; set; }
|
|
public string? RequestSiteId { get; set; }
|
|
public Guid? MaterialId { get; set; }
|
|
public decimal? Quantity { get; set; }
|
|
public Guid? ContainerId { get; set; }
|
|
public Guid? SourceStorageId { get; set; }
|
|
public Guid? TargetStorageId { get; set; }
|
|
public string? BatchNo { get; set; }
|
|
public int Priority { get; set; }
|
|
public string Reason { get; set; } = "";
|
|
|
|
public WmsTransportRequest ToRequest() => new(
|
|
TriggerType, RuleId, RequestSiteId, MaterialId, Quantity,
|
|
ContainerId, SourceStorageId, TargetStorageId, BatchNo,
|
|
Priority, Reason, null);
|
|
}
|