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

148 lines
5.6 KiB
C#

using System.Text.Json;
using System.Text.RegularExpressions;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Assets;
using Tiku.Application.Catalog;
using Tiku.Application.Content;
using Tiku.Application.Learning;
using Tiku.Application.QuestionBanks;
using Tiku.Application.Security;
using Tiku.Domain.Catalog;
using Tiku.Domain.Common;
using Tiku.Domain.Content;
using Tiku.Domain.Learning;
using Tiku.Domain.Operations;
using Tiku.Domain.QuestionBanks;
using Tiku.Infrastructure.Persistence;
using Tiku.Infrastructure.Security;
namespace Tiku.Infrastructure.Content;
public sealed partial class DirectContentService
{
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));
}
}