diff --git a/tests/SIGCM2.Api.Tests/Products/ProductTypeDeactivationGuardTests.cs b/tests/SIGCM2.Api.Tests/Products/ProductTypeDeactivationGuardTests.cs
new file mode 100644
index 0000000..1d244ed
--- /dev/null
+++ b/tests/SIGCM2.Api.Tests/Products/ProductTypeDeactivationGuardTests.cs
@@ -0,0 +1,158 @@
+using System.Net;
+using System.Net.Http.Headers;
+using System.Net.Http.Json;
+using System.Text.Json;
+using SIGCM2.TestSupport;
+
+namespace SIGCM2.Api.Tests.Products;
+
+///
+/// PRD-002 Batch 8 — Guard proof: verifies that deactivating a ProductType with active Products
+/// returns HTTP 409 Conflict. This test closes the W1 (dormant guard) issue from PRD-001:
+/// - PRD-001: NullProductQueryRepository always returned false → guard never fired
+/// - PRD-002: ProductQueryRepository now queries dbo.Product → guard fires correctly
+///
+[Collection("ApiIntegration")]
+public sealed class ProductTypeDeactivationGuardTests : IAsyncLifetime
+{
+ private const string AdminUsername = "admin";
+ private const string AdminPassword = "@Diego550@";
+
+ private readonly HttpClient _client;
+
+ public ProductTypeDeactivationGuardTests(TestWebAppFactory factory)
+ {
+ _client = factory.CreateClient();
+ }
+
+ public Task InitializeAsync() => Task.CompletedTask;
+ public Task DisposeAsync() => Task.CompletedTask;
+
+ private async Task GetAdminTokenAsync()
+ {
+ var response = await _client.PostAsJsonAsync("/api/v1/auth/login", new
+ {
+ username = AdminUsername,
+ password = AdminPassword
+ });
+ response.EnsureSuccessStatusCode();
+ var json = await response.Content.ReadFromJsonAsync();
+ return json.GetProperty("accessToken").GetString()!;
+ }
+
+ private HttpRequestMessage BuildRequest(HttpMethod method, string url, object? body = null, string? bearerToken = null)
+ {
+ var request = new HttpRequestMessage(method, url);
+ if (bearerToken is not null)
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
+ if (body is not null)
+ request.Content = JsonContent.Create(body);
+ return request;
+ }
+
+ ///
+ /// E2E proof: seed Medio + ProductType + active Product → DELETE product-type → expect 409.
+ /// This verifies the IProductQueryRepository guard fires against real data in dbo.Product.
+ ///
+ [Fact]
+ public async Task DeactivateProductType_WithActiveProducts_Returns409Conflict()
+ {
+ var token = await GetAdminTokenAsync();
+
+ // 1. Create a Medio
+ var medioResp = await _client.SendAsync(BuildRequest(HttpMethod.Post, "/api/v1/admin/medios", new
+ {
+ codigo = $"GD{Guid.NewGuid():N}"[..6],
+ nombre = $"Guarda Medio {Guid.NewGuid():N}"[..30],
+ tipo = 1
+ }, token));
+ medioResp.EnsureSuccessStatusCode();
+ var medioJson = await medioResp.Content.ReadFromJsonAsync();
+ var medioId = medioJson.GetProperty("id").GetInt32();
+
+ // 2. Create a ProductType
+ var ptResp = await _client.SendAsync(BuildRequest(HttpMethod.Post, "/api/v1/admin/product-types", new
+ {
+ nombre = $"Guardado PT {Guid.NewGuid():N}"[..30],
+ hasDuration = false, requiresText = false, requiresCategory = false, isBundle = false,
+ allowImages = false
+ }, token));
+ ptResp.EnsureSuccessStatusCode();
+ var ptJson = await ptResp.Content.ReadFromJsonAsync();
+ var productTypeId = ptJson.GetProperty("id").GetInt32();
+
+ // 3. Create an active Product for this ProductType
+ var prodResp = await _client.SendAsync(BuildRequest(HttpMethod.Post, "/api/v1/admin/products", new
+ {
+ nombre = $"Prod Guarda {Guid.NewGuid():N}"[..28],
+ medioId,
+ productTypeId,
+ basePrice = 100m
+ }, token));
+ prodResp.EnsureSuccessStatusCode();
+
+ // 4. Attempt to deactivate the ProductType — should be blocked by guard
+ using var deactivateReq = BuildRequest(HttpMethod.Delete, $"/api/v1/admin/product-types/{productTypeId}", bearerToken: token);
+ var deactivateResp = await _client.SendAsync(deactivateReq);
+
+ // CRITICAL ASSERTION: 409 Conflict — guard fires because Product is active
+ Assert.Equal(HttpStatusCode.Conflict, deactivateResp.StatusCode);
+
+ var body = await deactivateResp.Content.ReadFromJsonAsync();
+ Assert.Equal("product_type_en_uso", body.GetProperty("error").GetString());
+ }
+
+ ///
+ /// Verify guard does NOT block deactivation when Products exist but are all inactive.
+ ///
+ [Fact]
+ public async Task DeactivateProductType_WithOnlyInactiveProducts_Returns204()
+ {
+ var token = await GetAdminTokenAsync();
+
+ // 1. Create Medio
+ var medioResp = await _client.SendAsync(BuildRequest(HttpMethod.Post, "/api/v1/admin/medios", new
+ {
+ codigo = $"GI{Guid.NewGuid():N}"[..6],
+ nombre = $"Guarda Inact {Guid.NewGuid():N}"[..28],
+ tipo = 1
+ }, token));
+ medioResp.EnsureSuccessStatusCode();
+ var medioJson = await medioResp.Content.ReadFromJsonAsync();
+ var medioId = medioJson.GetProperty("id").GetInt32();
+
+ // 2. Create ProductType
+ var ptResp = await _client.SendAsync(BuildRequest(HttpMethod.Post, "/api/v1/admin/product-types", new
+ {
+ nombre = $"PT Inact {Guid.NewGuid():N}"[..28],
+ hasDuration = false, requiresText = false, requiresCategory = false, isBundle = false,
+ allowImages = false
+ }, token));
+ ptResp.EnsureSuccessStatusCode();
+ var ptJson = await ptResp.Content.ReadFromJsonAsync();
+ var productTypeId = ptJson.GetProperty("id").GetInt32();
+
+ // 3. Create then deactivate Product
+ var prodResp = await _client.SendAsync(BuildRequest(HttpMethod.Post, "/api/v1/admin/products", new
+ {
+ nombre = $"Prod Inact {Guid.NewGuid():N}"[..28],
+ medioId,
+ productTypeId,
+ basePrice = 50m
+ }, token));
+ prodResp.EnsureSuccessStatusCode();
+ var prodJson = await prodResp.Content.ReadFromJsonAsync();
+ var productId = prodJson.GetProperty("id").GetInt32();
+
+ // Deactivate the Product first
+ using var deactivateProdReq = BuildRequest(HttpMethod.Delete, $"/api/v1/admin/products/{productId}", bearerToken: token);
+ var deactivateProdResp = await _client.SendAsync(deactivateProdReq);
+ Assert.Equal(HttpStatusCode.NoContent, deactivateProdResp.StatusCode);
+
+ // 4. Now deactivate ProductType — should succeed since no active products
+ using var deactivatePtReq = BuildRequest(HttpMethod.Delete, $"/api/v1/admin/product-types/{productTypeId}", bearerToken: token);
+ var deactivatePtResp = await _client.SendAsync(deactivatePtReq);
+
+ Assert.Equal(HttpStatusCode.NoContent, deactivatePtResp.StatusCode);
+ }
+}