diff --git a/JobFlow.API/Services/OrganizationRealtimeNotifier.cs b/JobFlow.API/Services/OrganizationRealtimeNotifier.cs index 0a3b236..fb0481f 100644 --- a/JobFlow.API/Services/OrganizationRealtimeNotifier.cs +++ b/JobFlow.API/Services/OrganizationRealtimeNotifier.cs @@ -8,14 +8,17 @@ namespace JobFlow.API.Services; public class OrganizationRealtimeNotifier : IOrganizationRealtimeNotifier { private readonly IHubContext _notifierHub; + private readonly ILogger _logger; - public OrganizationRealtimeNotifier(IHubContext notifierHub) + public OrganizationRealtimeNotifier(IHubContext notifierHub, ILogger logger) { _notifierHub = notifierHub; + _logger = logger; } public async Task NotifyJobStatusChangedAsync(Guid organizationId, Guid jobId, string jobTitle, JobLifecycleStatus status) { + _logger.LogInformation("SignalR → JobStatusChanged | org:{OrgId} | job:{JobId}", organizationId, jobId); await _notifierHub.Clients.Group($"org:{organizationId}:dashboard") .SendAsync("JobStatusChanged", new { @@ -28,6 +31,7 @@ await _notifierHub.Clients.Group($"org:{organizationId}:dashboard") public async Task NotifyAssignmentChangedAsync(Guid organizationId, Guid jobId, Guid assignmentId) { + _logger.LogInformation("SignalR → AssignmentChanged | org:{OrgId} | assignment:{AssignmentId}", organizationId, assignmentId); await _notifierHub.Clients.Group($"org:{organizationId}:dashboard") .SendAsync("AssignmentChanged", new { diff --git a/JobFlow.Business/Services/AssignmentService.cs b/JobFlow.Business/Services/AssignmentService.cs index 39b278f..03e1ca5 100644 --- a/JobFlow.Business/Services/AssignmentService.cs +++ b/JobFlow.Business/Services/AssignmentService.cs @@ -207,6 +207,12 @@ public async Task> UpdateAssignmentStatusAsync( await _realtimeNotifier.NotifyAssignmentChangedAsync( organizationId, assignment.JobId, assignmentId); + // When assignment starts, promote the job to InProgress if not already active + if (dto.Status == AssignmentStatus.InProgress) + { + await TryStartJobAsync(organizationId, assignment.JobId); + } + // When assignment is completed, check if all assignments for the job are done if (dto.Status == AssignmentStatus.Completed) { @@ -374,6 +380,27 @@ private async Task MapToDtoAsync(Guid organizationId, Assignment return MapToDto(assignment, labelMap); } + private async Task TryStartJobAsync(Guid organizationId, Guid jobId) + { + var job = await _jobs.Query() + .Include(j => j.OrganizationClient) + .FirstOrDefaultAsync(j => j.Id == jobId); + + if (job == null) return; + + var promotable = new[] { JobLifecycleStatus.Draft, JobLifecycleStatus.Approved, JobLifecycleStatus.Booked }; + if (!promotable.Contains(job.LifecycleStatus)) return; + + var result = await _jobService.UpdateJobStatusAsync(organizationId, jobId, JobLifecycleStatus.InProgress); + if (result.IsFailure) + { + _logger.LogWarning( + "Auto-start failed for job {JobId} after assignment began: {Error}", + jobId, + result.Error.Description); + } + } + private async Task TryCompleteJobAsync(Guid organizationId, Guid jobId) { var allJobAssignments = await _assignments.Query()