refactor(jobs): extract lifecycle endpoints

This commit is contained in:
cesnimda
2026-08-31 11:50:48 +02:00
parent 3fa828be47
commit 2f146f743c
5 changed files with 127 additions and 89 deletions
@@ -955,11 +955,6 @@ Canonical profile:
return string.Join(' ', words);
}
/// <summary>Canonical ordered pipeline stages so the UI renders one source of truth.</summary>
[HttpGet("pipeline")]
public ActionResult<IEnumerable<PipelineStageDto>> GetPipeline()
=> Ok(JobPipeline.Stages.Select(s => new PipelineStageDto(s.Key, s.Order, s.Category.ToString(), s.Group.ToString())));
[HttpPatch("{id:int}/status")]
public async Task<IActionResult> UpdateStatus([FromRoute] int id, [FromBody] UpdateStatusRequest request, CancellationToken cancellationToken)
{
@@ -1094,87 +1089,6 @@ Canonical profile:
return Ok(BuildJobApplicationDto(job, followUp));
}
[HttpDelete("{id:int}")]
public async Task<IActionResult> SoftDelete([FromRoute] int id, CancellationToken cancellationToken)
{
var job = await _db.JobApplications.FirstOrDefaultAsync(j => j.Id == id, cancellationToken);
if (job is null) return NotFound();
if (!job.IsDeleted)
{
job.IsDeleted = true;
job.DeletedAt = DateTime.Now;
_db.JobEvents.Add(new JobEvent
{
JobApplicationId = job.Id,
Type = "Deleted",
At = DateTime.Now
});
await _db.SaveChangesAsync(cancellationToken);
}
return NoContent();
}
[HttpPost("{id:int}/restore")]
public async Task<IActionResult> Restore([FromRoute] int id, CancellationToken cancellationToken)
{
var job = await _db.JobApplications.FirstOrDefaultAsync(j => j.Id == id, cancellationToken);
if (job is null) return NotFound();
if (job.IsDeleted)
{
job.IsDeleted = false;
job.DeletedAt = null;
_db.JobEvents.Add(new JobEvent
{
JobApplicationId = job.Id,
Type = "Restored",
At = DateTime.Now
});
await _db.SaveChangesAsync(cancellationToken);
}
return NoContent();
}
[HttpPatch("{id:int}/followup")]
public async Task<IActionResult> SetFollowUp([FromRoute] int id, [FromBody] FollowUpRequest request, CancellationToken cancellationToken)
{
var job = await _db.JobApplications.FirstOrDefaultAsync(j => j.Id == id, cancellationToken);
if (job is null) return NotFound();
var old = job.FollowUpAt?.ToString("o");
job.FollowUpAt = request.FollowUpAt;
_db.JobEvents.Add(new JobEvent
{
JobApplicationId = job.Id,
Type = "FollowUpSet",
OldValue = old,
NewValue = request.FollowUpAt?.ToString("o"),
At = DateTime.Now
});
await _db.SaveChangesAsync(cancellationToken);
return NoContent();
}
[HttpGet("{id:int}/history")]
public async Task<ActionResult<List<JobEventDto>>> GetHistory([FromRoute] int id, CancellationToken cancellationToken)
{
var exists = await _db.JobApplications.AnyAsync(j => j.Id == id, cancellationToken);
if (!exists) return NotFound();
var items = await _db.JobEvents
.AsNoTracking()
.Where(e => e.JobApplicationId == id)
.OrderByDescending(e => e.At)
.Select(e => new JobEventDto(e.Id, e.Type, e.OldValue, e.NewValue, e.Note, e.At))
.ToListAsync(cancellationToken);
return Ok(items);
}
private static string BuildPackageModeInstruction(string? mode)
{
return (mode ?? string.Empty).Trim().ToLowerInvariant() switch