feat(backend): add communication, tester, admin and middleman modules

Implement step 17 modules: threads/messages, notifications with automation (submission.created, idea.created, grant_call.opened), innovation test feedback, admin panel (submissions, verify, metrics, grant call status), Middleman adaptation and partnerships. Split multi-type files into one type per file and replace object-valued dictionaries with string-valued maps in data contracts (migrations 0006/0007).
This commit is contained in:
Rafał Tyński
2026-10-04 03:49:45 +02:00
parent f4f3b3896a
commit fa1199539b
136 changed files with 2338 additions and 574 deletions
+35 -1
View File
@@ -16,11 +16,16 @@ public class InnovationsController : ControllerBase
{
private readonly IInnovationService _innovations;
private readonly IMatchmakingService _matchmakingService;
private readonly ITestFeedbackService _testFeedback;
public InnovationsController(IInnovationService innovations, IMatchmakingService matchmakingService)
public InnovationsController(
IInnovationService innovations,
IMatchmakingService matchmakingService,
ITestFeedbackService testFeedback)
{
_innovations = innovations;
_matchmakingService = matchmakingService;
_testFeedback = testFeedback;
}
[HttpGet]
@@ -85,6 +90,35 @@ public class InnovationsController : ControllerBase
return updated is null ? NotFound() : Ok(updated);
}
[HttpPost("{innovationId}/test-feedback")]
public async Task<ActionResult<TestFeedbackResponse>> CreateTestFeedback(
string innovationId,
CreateTestFeedbackRequest request,
CancellationToken cancellationToken)
{
var userId = User.GetUserId();
if (string.IsNullOrWhiteSpace(userId))
{
return Unauthorized();
}
var feedback = await _testFeedback.CreateAsync(innovationId, userId, request, cancellationToken);
return feedback is null ? NotFound() : StatusCode(StatusCodes.Status201Created, feedback);
}
[HttpGet("{innovationId}/test-feedback")]
[Authorize(Policy = Policies.ManagerOrAbove)]
public async Task<ActionResult<IReadOnlyList<TestFeedbackResponse>>> ListTestFeedback(
string innovationId,
CancellationToken cancellationToken)
{
var feedback = await _testFeedback.ListForInnovationAsync(innovationId, cancellationToken);
return Ok(feedback);
}
private bool ValidateStage(string? stage) => InnovationStageWire.IsValid(stage);
private ActionResult InvalidStage()