Files
tiku-backend.net/Tiku.Infrastructure/Content/Questions/QuestionManagementService.cs

117 lines
5.2 KiB
C#

using Microsoft.EntityFrameworkCore;
using Tiku.Application.Content;
using Tiku.Application.Security;
using Tiku.Domain.QuestionBanks;
namespace Tiku.Infrastructure.Content;
internal sealed class QuestionManagementService(DirectContentServiceDependencies dependencies)
: DirectContentServiceBase(dependencies), IQuestionManagementService
{
public async Task<ContentManagementResult<QuestionManagementItem>> CreateQuestionAsync(
DirectContentActor actor,
QuestionWriteCommand command,
CancellationToken cancellationToken = default)
{
ValidateQuestionForPublication(command);
await AssertQuestionReferencesAsync(actor.TenantId, command, cancellationToken);
await using var transaction = dbContext.Database.CurrentTransaction is null
? await dbContext.Database.BeginTransactionAsync(cancellationToken)
: null;
var question = new Question
{
Id = command.QuestionId ?? Guid.NewGuid(),
TenantId = actor.TenantId
};
ApplyQuestion(question, command);
if (question.Status != QuestionStatus.Archived)
await featureAccessService.ConsumeQuotaIfConfiguredAsync(
actor.TenantId,
SaasQuotaMetricCatalog.PrivateQuestionCount,
cancellationToken: cancellationToken);
dbContext.Questions.Add(question);
await dbContext.SaveChangesAsync(cancellationToken);
var version = BuildQuestionVersion(actor, question.Id, 1, command);
dbContext.QuestionVersions.Add(version);
question.CurrentVersionId = version.Id;
await SyncPrimaryCollectionItemAsync(actor, question, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
if (transaction is not null) await transaction.CommitAsync(cancellationToken);
return new ContentManagementResult<QuestionManagementItem>(ToQuestionItem(question, version));
}
public async Task<ContentManagementResult<QuestionManagementItem>> UpdateQuestionAsync(
DirectContentActor actor,
QuestionWriteCommand command,
CancellationToken cancellationToken = default)
{
if (!command.QuestionId.HasValue)
throw new ContentManagementException("questionId is required.", "question_id_required");
ValidateQuestionForPublication(command);
var question = await dbContext.Questions.SingleOrDefaultAsync(
item => item.TenantId == actor.TenantId && item.Id == command.QuestionId.Value,
cancellationToken);
if (question is null) throw new ContentManagementException("Question was not found.", "question_not_found");
await AssertQuestionReferencesAsync(actor.TenantId, command, cancellationToken);
await using var transaction = dbContext.Database.CurrentTransaction is null
? await dbContext.Database.BeginTransactionAsync(cancellationToken)
: null;
var wasCounted = question.Status != QuestionStatus.Archived;
ApplyQuestion(question, command);
var isCounted = question.Status != QuestionStatus.Archived;
if (!wasCounted && isCounted)
await featureAccessService.ConsumeQuotaIfConfiguredAsync(
actor.TenantId,
SaasQuotaMetricCatalog.PrivateQuestionCount,
cancellationToken: cancellationToken);
QuestionVersion? version;
if (command.CreateVersion || !question.CurrentVersionId.HasValue)
{
var nextVersionNo = await dbContext.QuestionVersions
.Where(item => item.TenantId == actor.TenantId && item.QuestionId == question.Id)
.Select(item => (int?)item.VersionNo)
.MaxAsync(cancellationToken) ?? 0;
version = BuildQuestionVersion(actor, question.Id, nextVersionNo + 1, command);
dbContext.QuestionVersions.Add(version);
question.CurrentVersionId = version.Id;
}
else
{
version = await dbContext.QuestionVersions.SingleOrDefaultAsync(
item =>
item.TenantId == actor.TenantId &&
item.QuestionId == question.Id &&
item.Id == question.CurrentVersionId.Value,
cancellationToken);
if (version is null)
{
version = BuildQuestionVersion(actor, question.Id, 1, command);
dbContext.QuestionVersions.Add(version);
question.CurrentVersionId = version.Id;
}
else
{
ApplyQuestionVersion(version, command);
}
}
await SyncPrimaryCollectionItemAsync(actor, question, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
if (wasCounted && !isCounted)
await featureAccessService.ReleaseQuotaAsync(
actor.TenantId,
SaasQuotaMetricCatalog.PrivateQuestionCount,
1,
cancellationToken);
if (transaction is not null) await transaction.CommitAsync(cancellationToken);
return new ContentManagementResult<QuestionManagementItem>(ToQuestionItem(question, version));
}
}