fix(web): allow cancelling pending applications; drop contradictory message guard
PR Checks / test-and-build (pull_request) Successful in 7m50s
PR Checks / test-and-build (pull_request) Successful in 7m50s
Address review feedback from PR #119: - LeaveClubMembershipAsync: was rejecting Pending rows because the SQL required status = 'Active', so clicking "Отозвать заявку" on a Pending membership surfaced a misleading "Active membership X not found" InvalidOperationException. Now the method first tries Active -> Left and falls back to Pending -> Rejected so the same UI flow covers both states. - PublicClub.razor TrySubmitApplicationAsync: removed the empty-input guard that contradicted the "(необязательно)" label and the server side (AuthorizedMembershipService already trims and accepts null). No tests broken (493 still passing), no public-API changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -167,12 +167,6 @@ else if (club is not null)
|
|||||||
if (club is null)
|
if (club is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(applicationMessage))
|
|
||||||
{
|
|
||||||
applicationError = "Введите сообщение или оставьте поле пустым.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
isSubmittingApplication = true;
|
isSubmittingApplication = true;
|
||||||
|
|||||||
@@ -2707,6 +2707,7 @@ public sealed class SessionService(
|
|||||||
public async Task LeaveClubMembershipAsync(Guid membershipId, Guid playerId)
|
public async Task LeaveClubMembershipAsync(Guid membershipId, Guid playerId)
|
||||||
{
|
{
|
||||||
await using var conn = await dataSource.OpenConnectionAsync();
|
await using var conn = await dataSource.OpenConnectionAsync();
|
||||||
|
// Active membership: withdraw by setting status = 'Left'.
|
||||||
var rows = await conn.ExecuteAsync(
|
var rows = await conn.ExecuteAsync(
|
||||||
"""
|
"""
|
||||||
UPDATE club_memberships
|
UPDATE club_memberships
|
||||||
@@ -2714,9 +2715,22 @@ public sealed class SessionService(
|
|||||||
WHERE id = @MembershipId AND player_id = @PlayerId AND status = 'Active'
|
WHERE id = @MembershipId AND player_id = @PlayerId AND status = 'Active'
|
||||||
""",
|
""",
|
||||||
new { MembershipId = membershipId, PlayerId = playerId });
|
new { MembershipId = membershipId, PlayerId = playerId });
|
||||||
if (rows == 0)
|
if (rows > 0)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Active membership {membershipId} not found for player.");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pending application: cancel by setting status = 'Rejected' so the user can re-apply later.
|
||||||
|
var cancelled = await conn.ExecuteAsync(
|
||||||
|
"""
|
||||||
|
UPDATE club_memberships
|
||||||
|
SET status = 'Rejected', decided_at = now()
|
||||||
|
WHERE id = @MembershipId AND player_id = @PlayerId AND status = 'Pending'
|
||||||
|
""",
|
||||||
|
new { MembershipId = membershipId, PlayerId = playerId });
|
||||||
|
if (cancelled == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Membership {membershipId} is not Active or Pending for this player.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user