diff --git a/backend/API/Controllers/FilamentsController.cs b/backend/API/Controllers/FilamentsController.cs
index f39c81d..f5c1c9c 100644
--- a/backend/API/Controllers/FilamentsController.cs
+++ b/backend/API/Controllers/FilamentsController.cs
@@ -295,6 +295,66 @@ public class FilamentsController : ControllerBase
return Ok(MapToFilamentResponse(entity));
}
+ ///
+ /// Deletes a filament spool by its unique identifier.
+ /// If the spool has associated print jobs, the deletion is rejected with a 409 Conflict
+ /// to preserve COGS and print history — the caller should archive the spool instead.
+ /// Associated filament usage records are removed before the spool is deleted.
+ /// AMS slots referencing this spool will have their SpoolId set to null by the database.
+ ///
+ /// The unique identifier of the filament spool to delete.
+ /// No content on successful deletion.
+ /// The filament spool was successfully deleted.
+ /// If the filament spool with the given ID is not found.
+ /// If the spool has associated print jobs and cannot be deleted.
+ [HttpDelete("{id:guid}")]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesResponseType(StatusCodes.Status409Conflict)]
+ public async Task DeleteFilament(Guid id)
+ {
+ _logger.LogInformation("Deleting filament {Id}", id);
+
+ var entity = await _dbContext.Spools.FindAsync(id);
+ if (entity is null)
+ {
+ _logger.LogWarning("Filament {Id} not found for deletion", id);
+ return NotFound(new { error = $"Filament with ID '{id}' not found." });
+ }
+
+ // Check for associated print jobs — these cannot be orphaned
+ var hasPrintJobs = await _dbContext.PrintJobs.AnyAsync(pj => pj.SpoolId == id);
+ if (hasPrintJobs)
+ {
+ _logger.LogWarning(
+ "Cannot delete filament {Id}: associated print jobs exist. Suggest archiving instead.", id);
+ return Conflict(new
+ {
+ error = $"Cannot delete filament '{id}' because it has associated print jobs. " +
+ "Archive the filament instead to preserve print history and COGS data."
+ });
+ }
+
+ // Remove associated filament usage records (usage tracking data for this spool)
+ var usageRecords = await _dbContext.FilamentUsages
+ .Where(fu => fu.SpoolId == id)
+ .ToListAsync();
+
+ if (usageRecords.Count > 0)
+ {
+ _logger.LogInformation(
+ "Removing {Count} filament usage records for spool {Id}",
+ usageRecords.Count, id);
+ _dbContext.FilamentUsages.RemoveRange(usageRecords);
+ }
+
+ _dbContext.Spools.Remove(entity);
+ await _dbContext.SaveChangesAsync();
+
+ _logger.LogInformation("Filament {Id} deleted successfully", id);
+ return NoContent();
+ }
+
// ── Mapping helper ─────────────────────────────────────────
///