feat(data): TaskRepository.CreateChildAsync

This commit is contained in:
mika kuns
2026-04-23 17:54:43 +02:00
parent b466246c1b
commit 74255ddc82
2 changed files with 89 additions and 0 deletions

View File

@@ -217,6 +217,56 @@ public sealed class TaskRepository
.ToListAsync(ct); .ToListAsync(ct);
} }
public async Task<TaskEntity> CreateChildAsync(
string parentId,
string title,
string? description,
IReadOnlyList<string>? tagNames,
string? commitType,
CancellationToken ct = default)
{
var parent = await _context.Tasks.FirstOrDefaultAsync(t => t.Id == parentId, ct);
if (parent is null)
throw new InvalidOperationException($"Parent task {parentId} not found.");
var maxSort = await _context.Tasks
.Where(t => t.ListId == parent.ListId)
.Select(t => (int?)t.SortOrder)
.MaxAsync(ct);
var child = new TaskEntity
{
Id = Guid.NewGuid().ToString(),
ListId = parent.ListId,
Title = title,
Description = description,
Status = TaskStatus.Draft,
CreatedAt = DateTime.UtcNow,
CommitType = string.IsNullOrEmpty(commitType) ? parent.CommitType : commitType,
ParentTaskId = parentId,
SortOrder = (maxSort ?? -1) + 1,
};
_context.Tasks.Add(child);
if (tagNames is not null && tagNames.Count > 0)
{
foreach (var tagName in tagNames.Distinct(StringComparer.OrdinalIgnoreCase))
{
var tag = await _context.Tags.FirstOrDefaultAsync(t => t.Name == tagName, ct);
if (tag is null)
{
tag = new TagEntity { Name = tagName };
_context.Tags.Add(tag);
await _context.SaveChangesAsync(ct);
}
child.Tags.Add(tag);
}
}
await _context.SaveChangesAsync(ct);
return child;
}
#endregion #endregion
#region Queue selection #region Queue selection

View File

@@ -80,4 +80,43 @@ public sealed class TaskRepositoryPlanningTests : IDisposable
Assert.Equal("b", children[0].Title); Assert.Equal("b", children[0].Title);
Assert.Equal("a", children[1].Title); Assert.Equal("a", children[1].Title);
} }
[Fact]
public async Task CreateChildAsync_CreatesDraftUnderParent()
{
var listId = await CreateListAsync();
var parent = MakeTask(listId, TaskStatus.Planning);
await _tasks.AddAsync(parent);
var child = await _tasks.CreateChildAsync(
parent.Id,
title: "child title",
description: "child desc",
tagNames: new[] { "agent" },
commitType: "feat");
Assert.Equal(TaskStatus.Draft, child.Status);
Assert.Equal(parent.Id, child.ParentTaskId);
Assert.Equal(listId, child.ListId);
Assert.Equal("child title", child.Title);
Assert.Equal("child desc", child.Description);
Assert.Equal("feat", child.CommitType);
var loaded = await _tasks.GetByIdAsync(child.Id);
Assert.NotNull(loaded);
Assert.Equal(TaskStatus.Draft, loaded!.Status);
var tags = await _tasks.GetTagsAsync(child.Id);
Assert.Contains(tags, t => t.Name == "agent");
}
[Fact]
public async Task CreateChildAsync_ThrowsIfParentNotFound()
{
var listId = await CreateListAsync();
_ = listId; // just to create the DB
await Assert.ThrowsAsync<InvalidOperationException>(() =>
_tasks.CreateChildAsync("nonexistent-parent-id", "t", null, null, null));
}
} }