Upgrade dynamic questions to authored parity

This commit is contained in:
hz
2026-07-23 14:11:18 -05:00
parent e174b5db15
commit 92c5688b55
12 changed files with 690 additions and 18 deletions
@@ -27,7 +27,7 @@ public sealed class DynamicQuestionStore
}
public async Task<List<DynamicQuestionBlueprint>> PublishedAsync() =>
await _blueprints.Find(value => value.IsPublished).ToListAsync();
await _blueprints.Find(value => value.IsPublished && value.QualityStandardVersion >= 2).ToListAsync();
public async Task<DynamicQuestionBlueprint?> GetAsync(string externalId, int version) =>
await _blueprints.Find(value => value.ExternalId == externalId && value.Version == version).FirstOrDefaultAsync();
@@ -114,18 +114,32 @@ public sealed class DynamicQuestionStore
};
}
public async Task UpsertBlueprintsAsync(IEnumerable<DynamicQuestionBlueprint> blueprints)
public async Task<(int Inserted, int Unchanged)> UpsertBlueprintsAsync(IEnumerable<DynamicQuestionBlueprint> blueprints)
{
var inserted = 0;
var unchanged = 0;
foreach (var blueprint in blueprints)
{
var existing = await _blueprints.Find(
value => value.ExternalId == blueprint.ExternalId && value.Version == blueprint.Version)
.FirstOrDefaultAsync();
blueprint.Id = existing is null ? ObjectId.GenerateNewId().ToString() : existing.Id;
await _blueprints.ReplaceOneAsync(
value => value.ExternalId == blueprint.ExternalId && value.Version == blueprint.Version,
blueprint,
new ReplaceOptions { IsUpsert = true });
if (existing is not null)
{
blueprint.Id = existing.Id;
var incomingDocument = blueprint.ToBsonDocument();
var existingDocument = existing.ToBsonDocument();
incomingDocument.Remove("_id");
existingDocument.Remove("_id");
if (incomingDocument != existingDocument)
throw new InvalidDataException(
$"{blueprint.ExternalId} v{blueprint.Version} is immutable; publish changes with a new version");
unchanged++;
continue;
}
blueprint.Id = ObjectId.GenerateNewId().ToString();
await _blueprints.InsertOneAsync(blueprint);
inserted++;
}
return (inserted, unchanged);
}
}