mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 11:53:12 +00:00
fix(team-members): keep full-name round-trip stable on update
Storing the submitted full name in FirstName while leaving a seeded LastName intact made an unchanged save project a duplicated name (e.g. "Legacy Manager Manager"). Leave FirstName/LastName untouched when the submitted name already matches the stored first+last projection, and otherwise split the submitted name across FirstName/LastName so renames round-trip cleanly.
This commit is contained in:
parent
bdfe666b8d
commit
ba8907fad0
2 changed files with 70 additions and 1 deletions
|
|
@ -216,6 +216,57 @@ public sealed class TeamMemberServiceTests
|
|||
overrides.Verify(data => data.SetOverridesAsync(user.Id, It.Is<IReadOnlyDictionary<string, UserPermissionState>>(value => value["createSites"] == UserPermissionState.Deny), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Update_SavesUnchangedNameWithoutDuplicatingRoleLikeLastName()
|
||||
{
|
||||
var service = NewService(
|
||||
out var userManager,
|
||||
out var roleManager,
|
||||
out var areas,
|
||||
out _,
|
||||
out var userData,
|
||||
out var permissions);
|
||||
var user = new ApplicationUser
|
||||
{
|
||||
Id = "admin",
|
||||
FirstName = "Legacy",
|
||||
LastName = "Manager",
|
||||
Email = "legacy@example.com",
|
||||
Color = "#F59E0B",
|
||||
UniqueName = "Active"
|
||||
};
|
||||
userManager.Setup(manager => manager.FindByIdAsync(user.Id)).ReturnsAsync(user);
|
||||
userManager.Setup(manager => manager.GetRolesAsync(user)).ReturnsAsync(new List<string> { "Admin" });
|
||||
userManager.Setup(manager => manager.FindByEmailAsync(user.Email!)).ReturnsAsync(user);
|
||||
roleManager.Setup(manager => manager.RoleExistsAsync("Admin")).ReturnsAsync(true);
|
||||
areas.Setup(data => data.GetForUserAsync(user.Id, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(Array.Empty<string>());
|
||||
permissions.Setup(data => data.GetProfileAsync(user.Id, It.IsAny<ClaimsPrincipal>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(TeamPermissionResult<TeamPermissionProfileDTO>.Success(new TeamPermissionProfileDTO
|
||||
{
|
||||
UserId = user.Id,
|
||||
Permissions = Array.Empty<TeamPermissionValueDTO>()
|
||||
}));
|
||||
|
||||
var result = await service.UpdateAsync(
|
||||
user.Id,
|
||||
new UpdateTeamMemberRequestDTO
|
||||
{
|
||||
Name = "Legacy Manager",
|
||||
Role = "Admin",
|
||||
Color = "#F59E0B",
|
||||
Email = user.Email
|
||||
},
|
||||
Admin(),
|
||||
CancellationToken.None);
|
||||
|
||||
result.Success.Should().BeTrue();
|
||||
user.FirstName.Should().Be("Legacy");
|
||||
user.LastName.Should().Be("Manager");
|
||||
result.Member!.Name.Should().Be("Legacy Manager");
|
||||
userData.Verify(data => data.UpdateUserAsync(user, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Update_LeavesOmittedOverridesUnchanged()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ public sealed class TeamMemberService : ITeamMemberService
|
|||
if (roleError is not null)
|
||||
return OperationFailure(roleError);
|
||||
|
||||
user.FirstName = candidate.Name!.Trim();
|
||||
ApplyName(user, candidate.Name!.Trim());
|
||||
user.Contact = candidate.Phone?.Trim();
|
||||
user.PhoneNumber = candidate.Phone?.Trim();
|
||||
user.Color = color;
|
||||
|
|
@ -215,6 +215,24 @@ public sealed class TeamMemberService : ITeamMemberService
|
|||
return await OperationSuccessAsync(user, caller, cancellationToken);
|
||||
}
|
||||
|
||||
private static void ApplyName(ApplicationUser user, string fullName)
|
||||
{
|
||||
var current = $"{user.FirstName ?? ""} {user.LastName ?? ""}".Trim();
|
||||
if (string.Equals(fullName, current, StringComparison.Ordinal))
|
||||
return;
|
||||
|
||||
var separator = fullName.IndexOf(' ');
|
||||
if (separator < 0)
|
||||
{
|
||||
user.FirstName = fullName;
|
||||
user.LastName = null;
|
||||
return;
|
||||
}
|
||||
|
||||
user.FirstName = fullName[..separator].Trim();
|
||||
user.LastName = fullName[(separator + 1)..].Trim();
|
||||
}
|
||||
|
||||
private async Task<string?> EnsureRoleAsync(string role)
|
||||
{
|
||||
if (await _roleManager.RoleExistsAsync(role))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue