Initial import into Gitea
This commit is contained in:
84
Management/Controllers/Admin/AdminModifiersController.cs
Normal file
84
Management/Controllers/Admin/AdminModifiersController.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using Management.Data;
|
||||
using Management.Security;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Management.Controllers.Admin;
|
||||
|
||||
/// <summary>
|
||||
/// Admin endpoints for audience-based allocation modifiers.
|
||||
/// Table: dbo.tbAllocationModifier
|
||||
/// Proc: dbo.spAllocationRecommend (list / update actions)
|
||||
///
|
||||
/// ENDPOINTS:
|
||||
/// GET /api/admin/modifiers - List all modifiers
|
||||
/// PUT /api/admin/modifiers/{id} - Update a modifier
|
||||
/// POST /api/admin/modifiers/preview - Preview recommendation with factors
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/admin/modifiers")]
|
||||
public sealed class AdminModifiersController : AdminControllerBase
|
||||
{
|
||||
public AdminModifiersController(SqlService sql, ClientContext client, ILogger<AdminModifiersController> log)
|
||||
: base(sql, client, log) { }
|
||||
|
||||
[HttpGet]
|
||||
public Task<IActionResult> List(CancellationToken ct)
|
||||
=> CallProc("spAllocationRecommend", "list", new { }, ct);
|
||||
|
||||
[HttpPut("{id:int}")]
|
||||
public Task<IActionResult> Update(int id, [FromBody] UpdateModifierRequest request, CancellationToken ct)
|
||||
{
|
||||
if (request?.PctAdjustment is < -50 or > 50)
|
||||
return Task.FromResult(ValidationError("pctAdjustment must be between -50 and 50"));
|
||||
|
||||
Logger.LogWarning("[Admin] UpdateModifier | Id={Id} | By={User}", id, Client.Email);
|
||||
|
||||
return CallProc("spAllocationRecommend", "update", new
|
||||
{
|
||||
id,
|
||||
pctAdjustment = request?.PctAdjustment,
|
||||
minBudgetAdj = request?.MinBudgetAdj,
|
||||
rationale = request?.Rationale?.Trim(),
|
||||
isActive = request?.IsActive
|
||||
}, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preview a recommendation with given factors — same proc, recommend action.
|
||||
/// Lets admins test how modifiers affect channel mix without going through the wizard.
|
||||
/// </summary>
|
||||
[HttpPost("preview")]
|
||||
public Task<IActionResult> Preview([FromBody] PreviewRequest request, CancellationToken ct)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request?.BusinessCategory))
|
||||
return Task.FromResult(ValidationError("businessCategory is required"));
|
||||
if (string.IsNullOrWhiteSpace(request?.Objective))
|
||||
return Task.FromResult(ValidationError("objective is required"));
|
||||
|
||||
return CallProc("spAllocationRecommend", "recommend", new
|
||||
{
|
||||
businessCategory = request.BusinessCategory.Trim(),
|
||||
objective = request.Objective.Trim(),
|
||||
ageSkew = request.AgeSkew?.Trim(),
|
||||
marketScope = request.MarketScope?.Trim()
|
||||
}, ct);
|
||||
}
|
||||
}
|
||||
|
||||
// DTOs
|
||||
|
||||
public sealed class UpdateModifierRequest
|
||||
{
|
||||
public int? PctAdjustment { get; set; }
|
||||
public int? MinBudgetAdj { get; set; }
|
||||
public string? Rationale { get; set; }
|
||||
public bool? IsActive { get; set; }
|
||||
}
|
||||
|
||||
public sealed class PreviewRequest
|
||||
{
|
||||
public string? BusinessCategory { get; set; }
|
||||
public string? Objective { get; set; }
|
||||
public string? AgeSkew { get; set; }
|
||||
public string? MarketScope { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user