117 lines
5.3 KiB
C#
117 lines
5.3 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 = unitOfWork.Database.CurrentTransaction is null
|
|
? await unitOfWork.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);
|
|
questionBankPersistence.Questions.Add(question);
|
|
await unitOfWork.SaveChangesAsync(cancellationToken);
|
|
|
|
var version = BuildQuestionVersion(actor, question.Id, 1, command);
|
|
questionBankPersistence.QuestionVersions.Add(version);
|
|
question.CurrentVersionId = version.Id;
|
|
await SyncPrimaryCollectionItemAsync(actor, question, cancellationToken);
|
|
|
|
await unitOfWork.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 questionBankPersistence.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 = unitOfWork.Database.CurrentTransaction is null
|
|
? await unitOfWork.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 questionBankPersistence.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);
|
|
questionBankPersistence.QuestionVersions.Add(version);
|
|
question.CurrentVersionId = version.Id;
|
|
}
|
|
else
|
|
{
|
|
version = await questionBankPersistence.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);
|
|
questionBankPersistence.QuestionVersions.Add(version);
|
|
question.CurrentVersionId = version.Id;
|
|
}
|
|
else
|
|
{
|
|
ApplyQuestionVersion(version, command);
|
|
}
|
|
}
|
|
|
|
await SyncPrimaryCollectionItemAsync(actor, question, cancellationToken);
|
|
|
|
await unitOfWork.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));
|
|
}
|
|
}
|