Sms & Email
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
using ERPCore.Dtos.Common;
|
||||
using ERPCore.Dtos.Config;
|
||||
using ERPCore.Infra.Auth;
|
||||
using ERPCore.Services.OwnerReport;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ERPCore.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Day-end owner report settings (docs/DAY_END_OWNER_REPORT_PLAN.md §3.5) — recipients, schedule,
|
||||
/// preview, "send test now" and the send log. Gated on the Settings nav policy like the other
|
||||
/// configuration screens (BranchConfigController, GlAccountConfigController).
|
||||
/// </summary>
|
||||
[Route("api/v1/settings/owner-report")]
|
||||
[Authorize(Policy = NavPolicies.Prefix + "settings")]
|
||||
public sealed class OwnerReportController : ApiControllerBase
|
||||
{
|
||||
// One test send per minute (whole deployment) so the button can't be used to spam the owner.
|
||||
private static readonly SemaphoreSlim TestGate = new(1, 1);
|
||||
private static DateTime _lastTestUtc = DateTime.MinValue;
|
||||
|
||||
private readonly IOwnerReportService _service;
|
||||
|
||||
public OwnerReportController(IOwnerReportService service) => _service = service;
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(OwnerReportConfigDto), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<OwnerReportConfigDto>> Get(CancellationToken ct)
|
||||
{
|
||||
var result = await _service.GetAsync(ct);
|
||||
SetETag(result.RowVersion);
|
||||
return Ok(result.Value);
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[ProducesResponseType(typeof(OwnerReportConfigDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status412PreconditionFailed)]
|
||||
[ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
|
||||
public async Task<ActionResult<OwnerReportConfigDto>> Update([FromBody] UpdateOwnerReportConfigRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await _service.UpdateAsync(request, RequireIfMatch(), ct);
|
||||
SetETag(result.RowVersion);
|
||||
return Ok(result.Value);
|
||||
}
|
||||
|
||||
[HttpGet("preview")]
|
||||
[ProducesResponseType(typeof(OwnerReportPreviewDto), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<OwnerReportPreviewDto>> Preview([FromQuery] DateOnly? date, CancellationToken ct)
|
||||
=> Ok(await _service.PreviewAsync(date, ct));
|
||||
|
||||
[HttpPost("test")]
|
||||
[ProducesResponseType(typeof(IReadOnlyList<OwnerReportSendResultDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status429TooManyRequests)]
|
||||
public async Task<ActionResult<IReadOnlyList<OwnerReportSendResultDto>>> SendTest([FromBody] OwnerReportTestRequest? request, CancellationToken ct)
|
||||
{
|
||||
await TestGate.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
if (DateTime.UtcNow - _lastTestUtc < TimeSpan.FromMinutes(1))
|
||||
return StatusCode(StatusCodes.Status429TooManyRequests,
|
||||
new { title = "A test was sent less than a minute ago — wait a moment before sending another." });
|
||||
_lastTestUtc = DateTime.UtcNow;
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestGate.Release();
|
||||
}
|
||||
|
||||
return Ok(await _service.SendTestAsync(request?.Date, ct));
|
||||
}
|
||||
|
||||
[HttpGet("dispatches")]
|
||||
[ProducesResponseType(typeof(PagedResponse<OwnerReportDispatchDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PagedResponse<OwnerReportDispatchDto>>> Dispatches([FromQuery] PageQuery query, CancellationToken ct)
|
||||
=> Ok(await _service.ListDispatchesAsync(query, ct));
|
||||
}
|
||||
Reference in New Issue
Block a user