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
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record AdminMetricsResponse(
int Submissions,
int Problems,
int Ideas,
int Innovations,
int KnowledgeItems,
int Users,
int OpenGrantCalls,
int Applications);
@@ -1,28 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record GrantCallResponse(
string Id,
string Name,
DateTimeOffset OpensAt,
DateTimeOffset ClosesAt,
string Status,
string? ExternalId);
public sealed record CreateApplicationRequest(
[Required] string GrantCallId,
[Required] string IdeaId,
IReadOnlyDictionary<string, object?>? Content);
public sealed record UpdateApplicationRequest(
IReadOnlyDictionary<string, object?>? Content,
string? Status);
public sealed record ApplicationResponse(
string Id,
string GrantCallId,
string IdeaId,
IReadOnlyDictionary<string, object?> Content,
string Status,
DateTimeOffset CreatedAt);
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record ApplicationResponse(
string Id,
string GrantCallId,
string IdeaId,
IReadOnlyDictionary<string, string?> Content,
string Status,
DateTimeOffset CreatedAt);
-18
View File
@@ -1,18 +0,0 @@
namespace TarninaHub.Application.Dtos;
public sealed record RegisterRequest(string Phone, string? Email, string Password);
public sealed record LoginRequest(string Phone, string Password);
public sealed record UserResponse(
string Id,
string Phone,
string? Email,
string Role,
string? OrganizationId);
public sealed record TokenResponse(
string AccessToken,
string TokenType,
DateTimeOffset ExpiresAt,
UserResponse User);
@@ -1,6 +1,5 @@
namespace TarninaHub.Application.Dtos;
public sealed record GrantConsentRequest(string Scope, DateTimeOffset? ExpiresAt);
public sealed record ConsentResponse(
string Id,
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateApplicationRequest(
[Required] string GrantCallId,
[Required] string IdeaId,
IReadOnlyDictionary<string, string?>? Content);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateIdeaRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required, StringLength(4000, MinimumLength = 10)] string Description,
IdeaCardRequest? Card);
@@ -0,0 +1,7 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateMessageRequest(
[Required, StringLength(4000, MinimumLength = 1)] string Body);
@@ -0,0 +1,8 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreatePartnershipRequest(
[Required, StringLength(200, MinimumLength = 3)] string Subject,
IReadOnlyList<string>? Partners);
@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateSubmissionRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required, StringLength(4000, MinimumLength = 10)] string Description,
[Required] string ChallengeId,
[Required] string LocationId,
IReadOnlyList<string>? Keywords);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateTestFeedbackRequest(
[Range(1, 5)] int Rating,
string? Comment,
string? Improvements);
@@ -0,0 +1,8 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateThreadRequest(
[Required, StringLength(200, MinimumLength = 3)] string Subject,
IReadOnlyList<string>? Participants);
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record GrantCallResponse(
string Id,
string Name,
DateTimeOffset OpensAt,
DateTimeOffset ClosesAt,
string Status,
string? ExternalId);
@@ -0,0 +1,4 @@
namespace TarninaHub.Application.Dtos;
public sealed record GrantConsentRequest(string Scope, DateTimeOffset? ExpiresAt);
@@ -0,0 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record IdeaAssistRequest(string? Focus);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record IdeaAssistResponse(
IReadOnlyList<string> Suggestions,
string ImprovedDescription,
bool FromLlm);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record IdeaCardRequest(
string? Essence,
string? Audience,
string? Stage);
@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record IdeaCardResponse(
string Id,
string IdeaId,
string Essence,
string Audience,
string Stage);
-41
View File
@@ -1,41 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record IdeaCardRequest(
string? Essence,
string? Audience,
string? Stage);
public sealed record CreateIdeaRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required, StringLength(4000, MinimumLength = 10)] string Description,
IdeaCardRequest? Card);
public sealed record UpdateIdeaRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required, StringLength(4000, MinimumLength = 10)] string Description,
string? Status);
public sealed record IdeaCardResponse(
string Id,
string IdeaId,
string Essence,
string Audience,
string Stage);
public sealed record IdeaResponse(
string Id,
string Title,
string Description,
string AuthorId,
string Status,
IdeaCardResponse? Card,
DateTimeOffset? UpdatedAt);
public sealed record IdeaAssistRequest(string? Focus);
public sealed record IdeaAssistResponse(
IReadOnlyList<string> Suggestions,
string ImprovedDescription,
bool FromLlm);
+13
View File
@@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record IdeaResponse(
string Id,
string Title,
string Description,
string AuthorId,
string Status,
IdeaCardResponse? Card,
DateTimeOffset? UpdatedAt);
@@ -1,27 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record InnovationRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[StringLength(2000)] string? Summary,
[StringLength(8000)] string? Description,
[Required] string ChallengeId,
[Required] string Stage,
string? Cost,
IReadOnlyDictionary<string, object?>? Contact,
IReadOnlyList<IReadOnlyDictionary<string, object?>>? Media,
bool Published);
public sealed record InnovationResponse(
string Id,
string Title,
string Summary,
string Description,
string ChallengeId,
string Stage,
string? Cost,
IReadOnlyDictionary<string, object?>? Contact,
IReadOnlyList<IReadOnlyDictionary<string, object?>> Media,
bool Published,
DateTimeOffset? UpdatedAt);
@@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record InnovationRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[StringLength(2000)] string? Summary,
[StringLength(8000)] string? Description,
[Required] string ChallengeId,
[Required] string Stage,
string? Cost,
IReadOnlyDictionary<string, string?>? Contact,
IReadOnlyList<IReadOnlyDictionary<string, string?>>? Media,
bool Published);
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record InnovationResponse(
string Id,
string Title,
string Summary,
string Description,
string ChallengeId,
string Stage,
string? Cost,
IReadOnlyDictionary<string, string?>? Contact,
IReadOnlyList<IReadOnlyDictionary<string, string?>> Media,
bool Published,
DateTimeOffset? UpdatedAt);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record InstitutionProfile(
string? Type,
string? Area,
IReadOnlyList<string>? Audiences);
-27
View File
@@ -1,27 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record KnowledgeItemRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required] string Kind,
string? ChallengeId,
string? SourceUrl,
IReadOnlyList<IReadOnlyDictionary<string, object?>>? Attachments,
bool Published);
public sealed record KnowledgeItemResponse(
string Id,
string Title,
string Kind,
string? ChallengeId,
string? SourceUrl,
IReadOnlyList<IReadOnlyDictionary<string, object?>> Attachments,
bool Published,
DateTimeOffset? UpdatedAt);
public sealed record SocialChallengeResponse(
string Id,
string Name,
string Description,
int Order);
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record KnowledgeItemRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required] string Kind,
string? ChallengeId,
string? SourceUrl,
IReadOnlyList<IReadOnlyDictionary<string, string?>>? Attachments,
bool Published);
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record KnowledgeItemResponse(
string Id,
string Title,
string Kind,
string? ChallengeId,
string? SourceUrl,
IReadOnlyList<IReadOnlyDictionary<string, string?>> Attachments,
bool Published,
DateTimeOffset? UpdatedAt);
+4
View File
@@ -0,0 +1,4 @@
namespace TarninaHub.Application.Dtos;
public sealed record LoginRequest(string Phone, string Password);
+6
View File
@@ -0,0 +1,6 @@
namespace TarninaHub.Application.Dtos;
public sealed record MatchRequest(
int? MaxResults,
string? ChallengeId);
@@ -0,0 +1,7 @@
namespace TarninaHub.Application.Dtos;
public sealed record MatchResponse(
IReadOnlyList<SimilarCaseItem> SimilarCases,
IReadOnlyList<SolutionItem> Solutions,
bool Fallback);
@@ -1,23 +0,0 @@
namespace TarninaHub.Application.Dtos;
public sealed record MatchRequest(
int? MaxResults,
string? ChallengeId);
public sealed record SimilarCaseItem(
string Id,
string Title,
double Score);
public sealed record SolutionItem(
string InnovationId,
string Title,
string Stage,
string ChallengeId,
double Score,
string Rationale);
public sealed record MatchResponse(
IReadOnlyList<SimilarCaseItem> SimilarCases,
IReadOnlyList<SolutionItem> Solutions,
bool Fallback);
@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record MessageResponse(
string Id,
string ThreadId,
string AuthorId,
string Body,
DateTimeOffset CreatedAt);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record MiddlemanRequest(
[Required] string InnovationId,
InstitutionProfile? InstitutionProfile,
string? Needs);
@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record MiddlemanResponse(
string ServiceForm,
IReadOnlyList<string> RequiredResources,
string Rationale,
bool FromLlm);
@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record NotificationResponse(
string Id,
string Type,
IReadOnlyDictionary<string, string?> Payload,
DateTimeOffset? ReadAt,
DateTimeOffset CreatedAt);
@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record PartnershipResponse(
string Id,
string InitiatorId,
string Subject,
IReadOnlyList<string> Partners,
string Status);
@@ -0,0 +1,4 @@
namespace TarninaHub.Application.Dtos;
public sealed record RegisterRequest(string Phone, string? Email, string Password);
@@ -0,0 +1,7 @@
namespace TarninaHub.Application.Dtos;
public sealed record SimilarCaseItem(
string Id,
string Title,
double Score);
@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record SocialChallengeResponse(
string Id,
string Name,
string Description,
int Order);
+10
View File
@@ -0,0 +1,10 @@
namespace TarninaHub.Application.Dtos;
public sealed record SolutionItem(
string InnovationId,
string Title,
string Stage,
string ChallengeId,
double Score,
string Rationale);
+8
View File
@@ -0,0 +1,8 @@
namespace TarninaHub.Application.Dtos;
public sealed record StorageInfo(
string Engine,
string DataDirectory,
string Namespace,
string Database);
-25
View File
@@ -1,25 +0,0 @@
namespace TarninaHub.Application.Dtos;
public sealed class StorageProbe
{
public string Label { get; set; } = "probe";
public DateTimeOffset CreatedAt { get; set; }
}
public sealed record StorageInfo(
string Engine,
string DataDirectory,
string Namespace,
string Database);
public sealed record StorageStatusResponse(
string Engine,
string DataDirectory,
string Namespace,
string Database,
int ProbeCount);
public sealed record StorageProbeResponse(
string Label,
DateTimeOffset CreatedAt);
+9
View File
@@ -0,0 +1,9 @@
namespace TarninaHub.Application.Dtos;
public sealed class StorageProbe
{
public string Label { get; set; } = "probe";
public DateTimeOffset CreatedAt { get; set; }
}
@@ -0,0 +1,6 @@
namespace TarninaHub.Application.Dtos;
public sealed record StorageProbeResponse(
string Label,
DateTimeOffset CreatedAt);
@@ -0,0 +1,9 @@
namespace TarninaHub.Application.Dtos;
public sealed record StorageStatusResponse(
string Engine,
string DataDirectory,
string Namespace,
string Database,
int ProbeCount);
@@ -2,15 +2,6 @@ using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record CreateSubmissionRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required, StringLength(4000, MinimumLength = 10)] string Description,
[Required] string ChallengeId,
[Required] string LocationId,
IReadOnlyList<string>? Keywords);
public sealed record UpdateSubmissionStatusRequest(
[Required] string Status);
public sealed record SubmissionResponse(
string Id,
@@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record TestFeedbackResponse(
string Id,
string InnovationId,
string AuthorId,
int Rating,
string Comment,
string Improvements,
DateTimeOffset CreatedAt);
@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record ThreadResponse(
string Id,
string Subject,
IReadOnlyList<string> Participants,
DateTimeOffset CreatedAt,
IReadOnlyList<MessageResponse> Messages);
@@ -0,0 +1,8 @@
namespace TarninaHub.Application.Dtos;
public sealed record TokenResponse(
string AccessToken,
string TokenType,
DateTimeOffset ExpiresAt,
UserResponse User);
+7
View File
@@ -0,0 +1,7 @@
namespace TarninaHub.Application.Dtos;
public sealed record TrendPoint(
string ChallengeId,
string ChallengeName,
int SubmissionCount);
@@ -1,9 +1,5 @@
namespace TarninaHub.Application.Dtos;
public sealed record TrendPoint(
string ChallengeId,
string ChallengeName,
int SubmissionCount);
public sealed record TrendsResponse(
DateTimeOffset From,
@@ -0,0 +1,8 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record UpdateApplicationRequest(
IReadOnlyDictionary<string, string?>? Content,
string? Status);
@@ -0,0 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record UpdateGrantCallStatusRequest([Required] string Status);
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record UpdateIdeaRequest(
[Required, StringLength(200, MinimumLength = 3)] string Title,
[Required, StringLength(4000, MinimumLength = 10)] string Description,
string? Status);
@@ -0,0 +1,7 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record UpdateSubmissionStatusRequest(
[Required] string Status);
+9
View File
@@ -0,0 +1,9 @@
namespace TarninaHub.Application.Dtos;
public sealed record UserResponse(
string Id,
string Phone,
string? Email,
string Role,
string? OrganizationId);
@@ -0,0 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace TarninaHub.Application.Dtos;
public sealed record VerifyKnowledgeItemRequest(bool Verified);