Skip to content

Commit 81e1321

Browse files
authored
Merge pull request #22 from design-sparx/feat/2-add-products-api
Implement product and category modules with complete tracking
2 parents 3b79a3f + 4ca5156 commit 81e1321

34 files changed

+3033
-28
lines changed

Constants/Permissions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ public static class Projects
2727
public const string Edit = "Permissions.Projects.Edit";
2828
public const string Delete = "Permissions.Projects.Delete";
2929
}
30+
31+
public static class Products
32+
{
33+
public const string View = "Permissions.Products.View";
34+
public const string Create = "Permissions.Products.Create";
35+
public const string Edit = "Permissions.Products.Edit";
36+
public const string Delete = "Permissions.Products.Delete";
37+
}
38+
39+
public static class ProductCategories
40+
{
41+
public const string View = "Permissions.ProductCategories.View";
42+
public const string Create = "Permissions.ProductCategories.Create";
43+
public const string Edit = "Permissions.ProductCategories.Edit";
44+
public const string Delete = "Permissions.ProductCategories.Delete";
45+
}
3046

3147
// Helper method to get all permissions
3248
public static IEnumerable<string> GetAllPermissions()
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using AdminHubApi.Dtos.ProductCategory;
2+
using AdminHubApi.Entities;
3+
using AdminHubApi.Interfaces;
4+
using Microsoft.AspNetCore.Authorization;
5+
using Microsoft.AspNetCore.Mvc;
6+
7+
namespace AdminHubApi.Controllers;
8+
9+
[ApiController]
10+
[Route("api/product-categories")]
11+
[Authorize]
12+
public class ProductCategoriesController : ControllerBase
13+
{
14+
private readonly IProductCategoryService _productCategoryService;
15+
private readonly ILogger<ProductCategoriesController> _logger;
16+
17+
public ProductCategoriesController(IProductCategoryService productCategoryService,
18+
ILogger<ProductCategoriesController> logger)
19+
{
20+
_productCategoryService = productCategoryService;
21+
_logger = logger;
22+
}
23+
24+
[HttpGet]
25+
public async Task<ActionResult<IEnumerable<ProductCategory>>> GetAllCategories()
26+
{
27+
var productCategories = await _productCategoryService.GetAllAsync();
28+
29+
return Ok(productCategories);
30+
}
31+
32+
[HttpGet("{id}")]
33+
public async Task<ActionResult<ProductCategory>> GetCategory(Guid id)
34+
{
35+
var productCategories = await _productCategoryService.GetByIdAsync(id);
36+
37+
if (productCategories == null)
38+
{
39+
return NotFound();
40+
}
41+
42+
return Ok(productCategories);
43+
}
44+
45+
[HttpPost]
46+
public async Task<ActionResult<ProductCategory>> CreateCategory(CreateProductCategoryDto productCategoryDto)
47+
{
48+
var productCategory = new ProductCategory
49+
{
50+
Id = Guid.NewGuid(),
51+
Title = productCategoryDto.Title,
52+
Description = productCategoryDto.Description ?? string.Empty,
53+
CreatedById = productCategoryDto.CreatedById,
54+
ModifiedById = productCategoryDto.CreatedById,
55+
Created = DateTime.UtcNow,
56+
Modified = DateTime.UtcNow
57+
};
58+
59+
var result = await _productCategoryService.CreateAsync(productCategory);
60+
61+
if (!result.Succeeded)
62+
{
63+
return BadRequest(result.Errors);
64+
}
65+
66+
return CreatedAtAction(nameof(GetCategory), new { id = productCategory.Id }, result);
67+
}
68+
69+
[HttpPut("{id}")]
70+
public async Task<IActionResult> UpdateCategory(Guid id, UpdateProductCategoryDto updateProductCategoryDto)
71+
{
72+
var productCategoryResponse = await _productCategoryService.GetByIdAsync(id);
73+
74+
if (productCategoryResponse == null)
75+
{
76+
return NotFound();
77+
}
78+
79+
// Update the existing entity instead of creating a new one
80+
var existingCategory = productCategoryResponse.Data;
81+
existingCategory.Title = updateProductCategoryDto.Title;
82+
existingCategory.Description = updateProductCategoryDto.Description ?? string.Empty;
83+
existingCategory.ModifiedById = updateProductCategoryDto.ModifiedById;
84+
existingCategory.Modified = DateTime.UtcNow;
85+
86+
await _productCategoryService.UpdateAsync(existingCategory);
87+
88+
return Ok(existingCategory);
89+
}
90+
91+
[HttpDelete("{id}")]
92+
public async Task<IActionResult> DeleteCategory(Guid id)
93+
{
94+
var productCategoryResponse = await _productCategoryService.GetByIdAsync(id);
95+
96+
if (productCategoryResponse == null)
97+
{
98+
return NotFound();
99+
}
100+
101+
await _productCategoryService.DeleteAsync(id);
102+
103+
return NoContent();
104+
}
105+
}

Controllers/ProductsController.cs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using AdminHubApi.Dtos.Products;
2+
using AdminHubApi.Entities;
3+
using AdminHubApi.Interfaces;
4+
using Microsoft.AspNetCore.Authorization;
5+
using Microsoft.AspNetCore.Mvc;
6+
7+
namespace AdminHubApi.Controllers;
8+
9+
[ApiController]
10+
[Route("/api/products")]
11+
public class ProductsController : ControllerBase
12+
{
13+
private readonly IProductService _productService;
14+
private readonly ILogger<ProductsController> _logger;
15+
16+
public ProductsController(IProductService productService, ILogger<ProductsController> logger)
17+
{
18+
_productService = productService;
19+
_logger = logger;
20+
}
21+
22+
[HttpGet]
23+
public async Task<ActionResult<IEnumerable<ProductResponseDto>>> GetAllProducts()
24+
{
25+
var products = await _productService.GetAllAsync();
26+
27+
return Ok(products);
28+
}
29+
30+
[HttpGet("{id}")]
31+
public async Task<ActionResult<ProductDto>> GetProductById(Guid id)
32+
{
33+
var product = await _productService.GetByIdAsync(id);
34+
35+
if (product == null)
36+
{
37+
return NotFound();
38+
}
39+
40+
return Ok(product);
41+
}
42+
43+
[HttpPost]
44+
public async Task<ActionResult> CreateProduct(CreateProductDto createProductDto)
45+
{
46+
var product = new Product
47+
{
48+
Id = Guid.NewGuid(),
49+
Title = createProductDto.Title,
50+
Description = createProductDto.Description,
51+
Price = createProductDto.Price,
52+
QuantityInStock = createProductDto.QuantityInStock,
53+
SKU = createProductDto.SKU,
54+
ImageUrl = createProductDto.ImageUrl,
55+
Status = createProductDto.Status,
56+
CategoryId = createProductDto.CategoryId,
57+
CreatedById = createProductDto.CreatedById,
58+
Created = DateTime.UtcNow,
59+
Modified = DateTime.UtcNow
60+
};
61+
62+
var result = await _productService.CreateAsync(product);
63+
64+
if (!result.Succeeded)
65+
{
66+
return BadRequest(result.Errors);
67+
}
68+
69+
return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, result);
70+
}
71+
72+
[HttpPut("{id}")]
73+
[Authorize]
74+
public async Task<IActionResult> UpdateProduct(Guid id, UpdateProductDto updateProductDto)
75+
{
76+
var productResponse = await _productService.GetByIdAsync(id);
77+
78+
if (!productResponse.Succeeded)
79+
{
80+
return NotFound(productResponse);
81+
}
82+
83+
var existingProduct = productResponse.Data;
84+
existingProduct.Title = updateProductDto.Title;
85+
existingProduct.Description = updateProductDto.Description ?? string.Empty;
86+
existingProduct.ModifiedById = updateProductDto.ModifiedById;
87+
existingProduct.Modified = DateTime.UtcNow;
88+
89+
await _productService.UpdateAsync(existingProduct);
90+
91+
return Ok(existingProduct);
92+
}
93+
94+
[HttpDelete("{id}")]
95+
[Authorize]
96+
public async Task<IActionResult> DeleteProduct(Guid id)
97+
{
98+
var productResponse = await _productService.GetByIdAsync(id);
99+
100+
if (!productResponse.Succeeded)
101+
{
102+
return NotFound(productResponse);
103+
}
104+
105+
await _productService.DeleteAsync(id);
106+
107+
return NoContent();
108+
}
109+
110+
[HttpGet("status/{status}")]
111+
public async Task<ActionResult<IEnumerable<ProductResponseDto>>> GetProductsByStatus(ProductStatus status)
112+
{
113+
var products = await _productService.GetProductsByStatusAsync(status);
114+
115+
return Ok(products);
116+
}
117+
118+
[HttpGet("category/{categoryId}")]
119+
public async Task<ActionResult<IEnumerable<ProductResponseDto>>> GetProductsByCategory(Guid categoryId)
120+
{
121+
var products = await _productService.GetProductsByCategoryAsync(categoryId);
122+
123+
return Ok(products);
124+
}
125+
126+
[HttpGet("created-by/{createdById}")]
127+
public async Task<ActionResult<IEnumerable<ProductDto>>> GetProductsByCreatedBy(string createdById)
128+
{
129+
var products = await _productService.GetProductsByCreatedByAsync(createdById);
130+
131+
return Ok(products);
132+
}
133+
}

Data/ApplicationDbContext.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : ba
1212
public DbSet<Project> Projects { get; set; }
1313

1414
public DbSet<BlacklistedToken> BlacklistedTokens { get; set; }
15+
16+
public DbSet<Product> Products { get; set; }
17+
public DbSet<ProductCategory> ProductCategories { get; set; }
1518

1619
protected override void OnModelCreating(ModelBuilder builder)
1720
{

Data/Seeders/RoleSeeder.cs

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ public static class RoleSeeder
1212
public readonly static string ManagerRole = "Manager";
1313

1414
// Define all application roles
15-
public readonly static string[] ApplicationRoles = new[]
16-
{
15+
private readonly static string[] ApplicationRoles =
16+
[
1717
AdminRole,
1818
UserRole,
1919
ManagerRole
20-
};
20+
];
2121

2222
// Define role permissions
23-
private readonly static Dictionary<string, string[]> RolePermissions = new()
23+
private readonly static Dictionary<string, string[]> RolePermissions = new Dictionary<string, string[]>
2424
{
2525
{
26-
AdminRole, new[]
27-
{
26+
AdminRole, [
2827
Permissions.Users.View,
2928
Permissions.Users.Create,
3029
Permissions.Users.Edit,
@@ -36,31 +35,51 @@ public static class RoleSeeder
3635
Permissions.Projects.View,
3736
Permissions.Projects.Create,
3837
Permissions.Projects.Edit,
39-
Permissions.Projects.Delete
40-
// Add other admin permissions
41-
}
38+
Permissions.Projects.Delete,
39+
Permissions.Products.View,
40+
Permissions.Products.Create,
41+
Permissions.Products.Edit,
42+
Permissions.Products.Delete,
43+
Permissions.ProductCategories.View,
44+
Permissions.ProductCategories.Create,
45+
Permissions.ProductCategories.Edit,
46+
Permissions.ProductCategories.Delete
47+
]
4248
},
4349
{
44-
ManagerRole, new[]
45-
{
50+
ManagerRole, [
4651
Permissions.Users.View,
4752
Permissions.Users.Create,
4853
Permissions.Users.Edit,
4954
Permissions.Roles.View,
5055
Permissions.Projects.View,
5156
Permissions.Projects.Create,
5257
Permissions.Projects.Edit,
53-
Permissions.Projects.Delete
54-
// Add other manager permissions
55-
}
58+
Permissions.Projects.Delete,
59+
Permissions.Products.View,
60+
Permissions.Products.Create,
61+
Permissions.Products.Edit,
62+
Permissions.Products.Delete,
63+
Permissions.ProductCategories.View,
64+
Permissions.ProductCategories.Create,
65+
Permissions.ProductCategories.Edit,
66+
Permissions.ProductCategories.Delete
67+
]
5668
},
5769
{
58-
UserRole, new[]
59-
{
70+
UserRole, [
6071
Permissions.Users.View,
6172
Permissions.Users.Edit,
62-
Permissions.Projects.View
63-
}
73+
Permissions.Projects.View,
74+
Permissions.Products.View,
75+
Permissions.Products.Create,
76+
Permissions.Products.Edit,
77+
Permissions.Products.Delete,
78+
Permissions.ProductCategories.View,
79+
Permissions.ProductCategories.Create,
80+
Permissions.ProductCategories.Edit,
81+
Permissions.ProductCategories.Delete
82+
]
6483
}
6584
};
6685

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace AdminHubApi.Dtos.ProductCategory;
4+
5+
public class CreateProductCategoryDto
6+
{
7+
public string Title { get; set; } = string.Empty;
8+
public string? Description { get; set; }
9+
[Required]
10+
public string CreatedById { get; set; }
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace AdminHubApi.Dtos.ProductCategory;
2+
3+
public class ProductCategoryDto
4+
{
5+
public Guid Id { get; set; }
6+
public string Title { get; set; } = string.Empty;
7+
public string? Description { get; set; }
8+
public DateTime Created { get; set; }
9+
public DateTime Updated { get; set; }
10+
}

0 commit comments

Comments
 (0)