├── .gitignore ├── Controllers ├── ApiResponse.cs ├── CategoryController.cs ├── ProdutController.cs └── UserController.cs ├── EFCore ├── AppDbContext.cs ├── Category.cs ├── NewClass.cs ├── Order.cs ├── OrderProduct.cs ├── Product.cs └── User.cs ├── Mappers └── MappingProfile.cs ├── Migrations ├── 20240930145851_AddProduct.Designer.cs ├── 20240930145851_AddProduct.cs └── AppDbContextModelSnapshot.cs ├── Models ├── categories │ ├── CategoryDto.cs │ └── CreateCategoryDto.cs ├── orders │ ├── CreateOrderDto.cs │ ├── CreateOrderProductDto.cs │ ├── OrderDto.cs │ └── OrderProductDto.cs ├── products │ ├── CreateProdutDto.cs │ └── ProductDto.cs └── users │ ├── CreateUserDto.cs │ ├── UpdateUserDto.cs │ └── UserDto.cs ├── Program.cs ├── Properties └── launchSettings.json ├── README.md ├── Services ├── CategoryService.cs ├── OrderService.cs ├── ProductService.cs └── UserService.cs ├── appsettings.json ├── ecommerce-db-api.csproj ├── ecommerce-db-api.http └── ecommerce-db-api.sln /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled output 2 | bin/ 3 | obj/ 4 | 5 | # User-specific files 6 | .vscode/ 7 | .vs/ 8 | .idea/ 9 | 10 | # Logs and temporary files 11 | *.log 12 | logs/ 13 | *.tmp 14 | *.bak 15 | *.swp 16 | 17 | # Environment and secrets 18 | .env 19 | .env.local 20 | .env.*.local 21 | secrets.json 22 | appsettings.Development.json 23 | 24 | # Packages and generated code 25 | packages/ 26 | .nuget/packages/ 27 | Generated_Code/ 28 | 29 | # Docker files 30 | docker-compose.override.yml 31 | docker-compose.* 32 | Dockerfile.* 33 | .dockerignore 34 | 35 | # Database and cache 36 | *.db 37 | *.sqlite 38 | *.sqlite3 -------------------------------------------------------------------------------- /Controllers/ApiResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace ecommerce_db_api.Utilities 8 | { 9 | public class ApiResponse 10 | { 11 | // Central method to handle the creation of ApiResponseTemplate with ObjectResult 12 | private static IActionResult CreateApiResponse(T? data, string message, int statusCode, bool success) 13 | { 14 | var response = new ApiResponseTemplate(success, data, message, statusCode); 15 | return new ObjectResult(response) 16 | { 17 | StatusCode = statusCode 18 | }; 19 | } 20 | 21 | public static IActionResult Success(T data, string message = "Success") 22 | { 23 | return CreateApiResponse(data, message, StatusCodes.Status200OK, true); 24 | } 25 | 26 | public static IActionResult Created(T data, string message = "Resource Created") 27 | { 28 | return CreateApiResponse(data, message, StatusCodes.Status201Created, true); 29 | } 30 | 31 | public static IActionResult NotFound(string message = "Resource not found") 32 | { 33 | return CreateApiResponse(null, message, StatusCodes.Status404NotFound, false); 34 | } 35 | 36 | public static IActionResult Conflict(string message = "Conflict Detected") 37 | { 38 | return CreateApiResponse(null, message, StatusCodes.Status409Conflict, false); 39 | } 40 | 41 | public static IActionResult BadRequest(string message = "Bad request") 42 | { 43 | return CreateApiResponse(null, message, StatusCodes.Status400BadRequest, false); 44 | } 45 | 46 | public static IActionResult Unauthorized(string message = "Unauthorized access") 47 | { 48 | return CreateApiResponse(null, message, StatusCodes.Status401Unauthorized, false); 49 | } 50 | 51 | public static IActionResult Forbidden(string message = "Forbidden access") 52 | { 53 | return CreateApiResponse(null, message, StatusCodes.Status403Forbidden, false); 54 | } 55 | 56 | public static IActionResult ServerError(string message = "Internal server error") 57 | { 58 | return CreateApiResponse(null, message, StatusCodes.Status500InternalServerError, false); 59 | } 60 | } 61 | 62 | public class ApiResponseTemplate 63 | { 64 | public bool Success { get; set; } 65 | public T? Data { get; set; } 66 | public string Message { get; set; } 67 | public int StatusCode { get; set; } 68 | 69 | public ApiResponseTemplate(bool success, T? data, string message, int statusCode) 70 | { 71 | Success = success; 72 | Data = data; 73 | Message = message; 74 | StatusCode = statusCode; 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Controllers/CategoryController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.Models; 6 | using ecommerce_db_api.Services; 7 | using ecommerce_db_api.Utilities; 8 | using Microsoft.AspNetCore.Mvc; 9 | 10 | namespace ecommerce_db_api.Controllers 11 | { 12 | [ApiController, Route("/api/categories")] 13 | 14 | public class CategoryController : ControllerBase 15 | { 16 | private readonly CategoryService _categoryService; 17 | public CategoryController(CategoryService categoryService) 18 | { 19 | _categoryService = categoryService; 20 | } 21 | 22 | 23 | // POST => /api/categories => Create a category 24 | [HttpPost] 25 | public async Task CreateCategory([FromBody] CreateCategoryDto newCategory) 26 | { 27 | if (!ModelState.IsValid) 28 | { 29 | return ApiResponse.BadRequest("Invalid category Data"); 30 | } 31 | try 32 | { 33 | var category = await _categoryService.CreateCategoryServiceAsync(newCategory); 34 | return ApiResponse.Created(category, "Category is created"); 35 | } 36 | catch (ApplicationException ex) 37 | { 38 | return ApiResponse.ServerError("Server error: " + ex.Message); 39 | } 40 | catch (System.Exception ex) 41 | { 42 | return ApiResponse.ServerError("Server error: " + ex.Message); 43 | } 44 | } 45 | 46 | // GET => /api/categories => RETURN all the Categories 47 | [HttpGet] 48 | public async Task GetCategories() 49 | { 50 | try 51 | { 52 | var categories = await _categoryService.GetCategoryServiceAsync(); 53 | return ApiResponse.Success(categories, "Categories are returned succesfully"); 54 | } 55 | catch (ApplicationException ex) 56 | { 57 | return ApiResponse.ServerError("Server error: " + ex.Message); 58 | } 59 | catch (System.Exception ex) 60 | { 61 | return ApiResponse.ServerError("Server error: " + ex.Message); 62 | } 63 | } 64 | 65 | // // // GET => /api/users/{userId} => return a single User 66 | // [HttpGet("{userId}")] 67 | // public async Task GetUser(Guid userId) 68 | // { 69 | // try 70 | // { 71 | // var user = await _userService.GetUserServiceByIdAsync(userId); 72 | // if (user == null) 73 | // { 74 | // return ApiResponse.NotFound($"User with this id {userId} does not exist"); 75 | // } 76 | // return ApiResponse.Success(user, "User is returned succesfully"); 77 | // } 78 | // catch (ApplicationException ex) 79 | // { 80 | // return ApiResponse.ServerError("Server error: " + ex.Message); 81 | // } 82 | // catch (System.Exception ex) 83 | // { 84 | // return ApiResponse.ServerError("Server error: " + ex.Message); 85 | // } 86 | // } 87 | 88 | // // DELETE => /api/users/{userId} => delete a single User 89 | // [HttpDelete("{userId}")] 90 | // public async Task DeleteUser(Guid userId) 91 | // { 92 | // try 93 | // { 94 | // var result = await _userService.DeleteUserServiceByIdAsync(userId); 95 | // if (result == false) 96 | // { 97 | // return ApiResponse.NotFound($"User with this id {userId} does not exist"); 98 | // } 99 | // return ApiResponse.Success(result, "User is deleted succesfully"); 100 | // } 101 | // catch (ApplicationException ex) 102 | // { 103 | // return ApiResponse.ServerError("Server error: " + ex.Message); 104 | // } 105 | // catch (System.Exception ex) 106 | // { 107 | // return ApiResponse.ServerError("Server error: " + ex.Message); 108 | // } 109 | // } 110 | 111 | // // PUT => /api/users/{userId} => Update an User 112 | // [HttpPut("{userId}")] 113 | // public async Task UpdateUser([FromBody] UpdateUserDto updateUser, Guid userId) 114 | // { 115 | // if (!ModelState.IsValid) 116 | // { 117 | // return ApiResponse.BadRequest("Invalid User Data"); 118 | // } 119 | // try 120 | // { 121 | // var user = await _userService.UpdateUserServiceAsync(updateUser, userId); 122 | // return ApiResponse.Success(user, "User is updated"); 123 | // } 124 | // catch (ApplicationException ex) 125 | // { 126 | // return ApiResponse.ServerError("Server error: " + ex.Message); 127 | // } 128 | // catch (System.Exception ex) 129 | // { 130 | // return ApiResponse.ServerError("Server error: " + ex.Message); 131 | // } 132 | // } 133 | 134 | 135 | 136 | 137 | // ReadUsers 138 | // ReadUser 139 | // DeleteUser 140 | // UpdateUser 141 | // LoginUser 142 | // LogoutUser 143 | // banUser 144 | // unBanUser 145 | // UpdateUserRole 146 | // UpdateUserRole 147 | } 148 | } 149 | 150 | // Create => context.TableName.AddAsync(user), context.TableName.SaveChangesAsync() 151 | // Read all the data => context.TableName.ToListAsync() 152 | // Read a single data => context.TableName.FindAsync() 153 | // Update => context.TableName.Remove(user), context.TableName.SaveChangesAsync() 154 | // Delete => context.TableName.UpdateAsync(), context.TableName.SaveChangesAsync() 155 | 156 | // AutoMapper => Map automatically (Entity <=> Dtos) 157 | // Step 1: install extension 158 | // Step 2: add the service 159 | // Step 3: Create automapper class 160 | // Step 4: Create the service -------------------------------------------------------------------------------- /Controllers/ProdutController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.Models; 6 | using ecommerce_db_api.Models.products; 7 | using ecommerce_db_api.Services; 8 | using ecommerce_db_api.Utilities; 9 | using Microsoft.AspNetCore.Mvc; 10 | 11 | namespace ecommerce_db_api.Controllers 12 | { 13 | [ApiController, Route("/api/products")] 14 | 15 | public class ProductController : ControllerBase 16 | { 17 | private readonly ProductService _productService; 18 | public ProductController(ProductService productService) 19 | { 20 | _productService = productService; 21 | } 22 | 23 | 24 | // POST => /api/users => Create an User 25 | [HttpPost] 26 | public async Task CreateProduct([FromBody] CreateProdutDto newProduct) 27 | { 28 | if (!ModelState.IsValid) 29 | { 30 | return ApiResponse.BadRequest("Invalid product Data"); 31 | } 32 | try 33 | { 34 | var product = await _productService.CreateProductServiceAsync(newProduct); 35 | return ApiResponse.Created(product, "Product is created"); 36 | } 37 | catch (ApplicationException ex) 38 | { 39 | return ApiResponse.ServerError("Server error: " + ex.Message); 40 | } 41 | catch (System.Exception ex) 42 | { 43 | return ApiResponse.ServerError("Server error: " + ex.Message); 44 | } 45 | } 46 | 47 | // GET => /api/products => RETURN all the product 48 | [HttpGet] 49 | public async Task GetProducts() 50 | { 51 | try 52 | { 53 | Console.WriteLine($"----test1---------"); 54 | 55 | var products = await _productService.GetProductsServiceAsync(); 56 | Console.WriteLine($"----test2---------"); 57 | 58 | return ApiResponse.Success(products, "Products are returned succesfully"); 59 | } 60 | catch (ApplicationException ex) 61 | { 62 | return ApiResponse.ServerError("Server error: " + ex.Message); 63 | } 64 | catch (System.Exception ex) 65 | { 66 | return ApiResponse.ServerError("Server error: " + ex.Message); 67 | } 68 | } 69 | 70 | // // GET => /api/users/{userId} => return a single User 71 | // [HttpGet("{userId}")] 72 | // public async Task GetUser(Guid userId) 73 | // { 74 | // try 75 | // { 76 | // var user = await _userService.GetUserServiceByIdAsync(userId); 77 | // if (user == null) 78 | // { 79 | // return ApiResponse.NotFound($"User with this id {userId} does not exist"); 80 | // } 81 | // return ApiResponse.Success(user, "User is returned succesfully"); 82 | // } 83 | // catch (ApplicationException ex) 84 | // { 85 | // return ApiResponse.ServerError("Server error: " + ex.Message); 86 | // } 87 | // catch (System.Exception ex) 88 | // { 89 | // return ApiResponse.ServerError("Server error: " + ex.Message); 90 | // } 91 | // } 92 | 93 | // // DELETE => /api/users/{userId} => delete a single User 94 | // [HttpDelete("{userId}")] 95 | // public async Task DeleteUser(Guid userId) 96 | // { 97 | // try 98 | // { 99 | // var result = await _userService.DeleteUserServiceByIdAsync(userId); 100 | // if (result == false) 101 | // { 102 | // return ApiResponse.NotFound($"User with this id {userId} does not exist"); 103 | // } 104 | // return ApiResponse.Success(result, "User is deleted succesfully"); 105 | // } 106 | // catch (ApplicationException ex) 107 | // { 108 | // return ApiResponse.ServerError("Server error: " + ex.Message); 109 | // } 110 | // catch (System.Exception ex) 111 | // { 112 | // return ApiResponse.ServerError("Server error: " + ex.Message); 113 | // } 114 | // } 115 | 116 | // // PUT => /api/users/{userId} => Update an User 117 | // [HttpPut("{userId}")] 118 | // public async Task UpdateUser([FromBody] UpdateUserDto updateUser, Guid userId) 119 | // { 120 | // if (!ModelState.IsValid) 121 | // { 122 | // return ApiResponse.BadRequest("Invalid User Data"); 123 | // } 124 | // try 125 | // { 126 | // var user = await _userService.UpdateUserServiceAsync(updateUser, userId); 127 | // return ApiResponse.Success(user, "User is updated"); 128 | // } 129 | // catch (ApplicationException ex) 130 | // { 131 | // return ApiResponse.ServerError("Server error: " + ex.Message); 132 | // } 133 | // catch (System.Exception ex) 134 | // { 135 | // return ApiResponse.ServerError("Server error: " + ex.Message); 136 | // } 137 | // } 138 | 139 | 140 | 141 | 142 | // ReadUsers 143 | // ReadUser 144 | // DeleteUser 145 | // UpdateUser 146 | // LoginUser 147 | // LogoutUser 148 | // banUser 149 | // unBanUser 150 | // UpdateUserRole 151 | // UpdateUserRole 152 | } 153 | } 154 | 155 | // Create => context.TableName.AddAsync(user), context.TableName.SaveChangesAsync() 156 | // Read all the data => context.TableName.ToListAsync() 157 | // Read a single data => context.TableName.FindAsync() 158 | // Update => context.TableName.Remove(user), context.TableName.SaveChangesAsync() 159 | // Delete => context.TableName.UpdateAsync(), context.TableName.SaveChangesAsync() 160 | 161 | // AutoMapper => Map automatically (Entity <=> Dtos) 162 | // Step 1: install extension 163 | // Step 2: add the service 164 | // Step 3: Create automapper class 165 | // Step 4: Create the service -------------------------------------------------------------------------------- /Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.Models; 6 | using ecommerce_db_api.Services; 7 | using ecommerce_db_api.Utilities; 8 | using Microsoft.AspNetCore.Mvc; 9 | 10 | namespace ecommerce_db_api.Controllers 11 | { 12 | [ApiController, Route("/api/users")] 13 | 14 | public class UserController : ControllerBase 15 | { 16 | private readonly UserService _userService; 17 | public UserController(UserService userService) 18 | { 19 | _userService = userService; 20 | } 21 | 22 | 23 | // POST => /api/users => Create an User 24 | [HttpPost] 25 | public async Task CreateUser([FromBody] CreateUserDto newUser) 26 | { 27 | if (!ModelState.IsValid) 28 | { 29 | return ApiResponse.BadRequest("Invalid User Data"); 30 | } 31 | try 32 | { 33 | var user = await _userService.CreateUserServiceAsync(newUser); 34 | return ApiResponse.Created(user, "User is created"); 35 | } 36 | catch (ApplicationException ex) 37 | { 38 | return ApiResponse.ServerError("Server error: " + ex.Message); 39 | } 40 | catch (System.Exception ex) 41 | { 42 | return ApiResponse.ServerError("Server error: " + ex.Message); 43 | } 44 | } 45 | 46 | // GET => /api/users => RETURN all the Users 47 | [HttpGet] 48 | public async Task GetUsers() 49 | { 50 | try 51 | { 52 | var users = await _userService.GetUsersServiceAsync(); 53 | return ApiResponse.Success(users, "Users are returned succesfully"); 54 | } 55 | catch (ApplicationException ex) 56 | { 57 | return ApiResponse.ServerError("Server error: " + ex.Message); 58 | } 59 | catch (System.Exception ex) 60 | { 61 | return ApiResponse.ServerError("Server error: " + ex.Message); 62 | } 63 | } 64 | 65 | // GET => /api/users/{userId} => return a single User 66 | [HttpGet("{userId}")] 67 | public async Task GetUser(Guid userId) 68 | { 69 | try 70 | { 71 | var user = await _userService.GetUserServiceByIdAsync(userId); 72 | if (user == null) 73 | { 74 | return ApiResponse.NotFound($"User with this id {userId} does not exist"); 75 | } 76 | return ApiResponse.Success(user, "User is returned succesfully"); 77 | } 78 | catch (ApplicationException ex) 79 | { 80 | return ApiResponse.ServerError("Server error: " + ex.Message); 81 | } 82 | catch (System.Exception ex) 83 | { 84 | return ApiResponse.ServerError("Server error: " + ex.Message); 85 | } 86 | } 87 | 88 | // DELETE => /api/users/{userId} => delete a single User 89 | [HttpDelete("{userId}")] 90 | public async Task DeleteUser(Guid userId) 91 | { 92 | try 93 | { 94 | var result = await _userService.DeleteUserServiceByIdAsync(userId); 95 | if (result == false) 96 | { 97 | return ApiResponse.NotFound($"User with this id {userId} does not exist"); 98 | } 99 | return ApiResponse.Success(result, "User is deleted succesfully"); 100 | } 101 | catch (ApplicationException ex) 102 | { 103 | return ApiResponse.ServerError("Server error: " + ex.Message); 104 | } 105 | catch (System.Exception ex) 106 | { 107 | return ApiResponse.ServerError("Server error: " + ex.Message); 108 | } 109 | } 110 | 111 | // PUT => /api/users/{userId} => Update an User 112 | [HttpPut("{userId}")] 113 | public async Task UpdateUser([FromBody] UpdateUserDto updateUser, Guid userId) 114 | { 115 | if (!ModelState.IsValid) 116 | { 117 | return ApiResponse.BadRequest("Invalid User Data"); 118 | } 119 | try 120 | { 121 | var user = await _userService.UpdateUserServiceAsync(updateUser, userId); 122 | return ApiResponse.Success(user, "User is updated"); 123 | } 124 | catch (ApplicationException ex) 125 | { 126 | return ApiResponse.ServerError("Server error: " + ex.Message); 127 | } 128 | catch (System.Exception ex) 129 | { 130 | return ApiResponse.ServerError("Server error: " + ex.Message); 131 | } 132 | } 133 | 134 | 135 | 136 | 137 | // ReadUsers 138 | // ReadUser 139 | // DeleteUser 140 | // UpdateUser 141 | // LoginUser 142 | // LogoutUser 143 | // banUser 144 | // unBanUser 145 | // UpdateUserRole 146 | // UpdateUserRole 147 | } 148 | } 149 | 150 | // Create => context.TableName.AddAsync(user), context.TableName.SaveChangesAsync() 151 | // Read all the data => context.TableName.ToListAsync() 152 | // Read a single data => context.TableName.FindAsync() 153 | // Update => context.TableName.Remove(user), context.TableName.SaveChangesAsync() 154 | // Delete => context.TableName.UpdateAsync(), context.TableName.SaveChangesAsync() 155 | 156 | // AutoMapper => Map automatically (Entity <=> Dtos) 157 | // Step 1: install extension 158 | // Step 2: add the service 159 | // Step 3: Create automapper class 160 | // Step 4: Create the service -------------------------------------------------------------------------------- /EFCore/AppDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.Models.orders; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace ecommerce_db_api.EFCore 9 | { 10 | public class AppDbContext : DbContext 11 | { 12 | public AppDbContext(DbContextOptions options) : base(options) { } 13 | 14 | public DbSet Users { get; set; } 15 | public DbSet Categories { get; set; } 16 | public DbSet Products { get; set; } 17 | public DbSet Orders { get; set; } 18 | public DbSet OrderProducts { get; set; } 19 | 20 | protected override void OnModelCreating(ModelBuilder modelBuilder) 21 | { 22 | modelBuilder.Entity(entity => 23 | { 24 | entity.HasKey(u => u.UserId); // Primary Key configuration 25 | entity.Property(u => u.UserId).HasDefaultValueSql("uuid_generate_v4()"); // Generate UUID for new records 26 | entity.Property(u => u.UserName).IsRequired().HasMaxLength(100); 27 | entity.Property(u => u.Email).IsRequired().HasMaxLength(100); 28 | entity.HasIndex(u => u.Email).IsUnique(); 29 | entity.Property(u => u.Password).IsRequired(); 30 | entity.Property(u => u.Address).HasMaxLength(255); 31 | entity.Property(u => u.IsAdmin).HasDefaultValue(false); 32 | entity.Property(u => u.IsBanned).HasDefaultValue(false); 33 | entity.Property(u => u.CreatedAt).HasDefaultValueSql("CURRENT_TIMESTAMP"); 34 | }); 35 | 36 | modelBuilder.Entity(entity => 37 | { 38 | entity.HasKey(category => category.CategoryId); // Primary Key configuration 39 | entity.Property(category => category.CategoryId).HasDefaultValueSql("uuid_generate_v4()"); // Generate UUID for new records 40 | entity.Property(category => category.Name).IsRequired().HasMaxLength(100); 41 | entity.HasIndex(category => category.Name).IsUnique(); 42 | entity.Property(category => category.Slug).IsRequired().HasMaxLength(100); 43 | entity.Property(category => category.CreatedAt).HasDefaultValueSql("CURRENT_TIMESTAMP"); 44 | }); 45 | 46 | modelBuilder.Entity(entity => 47 | { 48 | entity.HasKey(p => p.ProductId); // Primary Key 49 | entity.Property(p => p.ProductId).HasDefaultValueSql("uuid_generate_v4()"); 50 | entity.Property(p => p.Name).IsRequired().HasMaxLength(255); 51 | entity.Property(p => p.CreatedAt).HasDefaultValueSql("CURRENT_TIMESTAMP"); 52 | }); 53 | 54 | modelBuilder.Entity() 55 | .HasMany(c => c.Products) 56 | .WithOne(p => p.Category) 57 | .HasForeignKey(p => p.CategoryId) 58 | .OnDelete(DeleteBehavior.Cascade); 59 | 60 | // modelBuilder.Entity() 61 | // .HasMany(u => u.orders) 62 | // .WithOne(o => o.User) 63 | // .HasForeignKey(o => o.UserId) 64 | // .OnDelete(DeleteBehavior.Cascade); 65 | 66 | // Many-to-Many relationship between Order and Product using OrderProduct as join table 67 | modelBuilder.Entity() 68 | .HasKey(op => new { op.OrderId, op.ProductId }); // Composite primary key 69 | 70 | modelBuilder.Entity() 71 | .HasOne(op => op.Order) 72 | .WithMany(o => o.OrderProducts) 73 | .HasForeignKey(op => op.OrderId); 74 | 75 | modelBuilder.Entity() 76 | .HasOne(op => op.Product) 77 | .WithMany(p => p.OrderProducts) 78 | .HasForeignKey(op => op.ProductId); 79 | 80 | 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /EFCore/Category.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Json.Serialization; 5 | using System.Threading.Tasks; 6 | 7 | namespace ecommerce_db_api.EFCore 8 | { 9 | public class Category 10 | { 11 | public Guid CategoryId { get; set; } 12 | public string Name { get; set; } = string.Empty; 13 | public string Slug { get; set; } = string.Empty; 14 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 15 | 16 | // 1-Many relationship => 1 category has multiple products 17 | // One-to-Many: A category has many products 18 | [JsonIgnore] 19 | public List Products { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /EFCore/NewClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.EFCore 7 | { 8 | public class NewClass 9 | { 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /EFCore/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Json.Serialization; 5 | using System.Threading.Tasks; 6 | using ecommerce_db_api.EFCore; 7 | 8 | namespace ecommerce_db_api.Models.orders 9 | { 10 | public class Order 11 | { 12 | public Guid OrderId { get; set; } // Primary Key 13 | 14 | public DateTime OrderDate { get; set; } 15 | 16 | // Foreign Key 17 | public Guid UserId { get; set; } 18 | 19 | // Navigation Property 20 | public User User { get; set; } 21 | 22 | [JsonIgnore] 23 | public List OrderProducts { get; set; } = new List(); 24 | } 25 | } -------------------------------------------------------------------------------- /EFCore/OrderProduct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.Models.orders; 6 | 7 | namespace ecommerce_db_api.EFCore 8 | { 9 | public class OrderProduct 10 | { 11 | public Guid OrderId { get; set; } 12 | public Order Order { get; set; } 13 | 14 | public Guid ProductId { get; set; } 15 | public Product Product { get; set; } 16 | 17 | public decimal Price { get; set; } 18 | public int Quantity { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /EFCore/Product.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Json.Serialization; 5 | using System.Threading.Tasks; 6 | 7 | namespace ecommerce_db_api.EFCore 8 | { 9 | public class Product 10 | { 11 | public Guid ProductId { get; set; } 12 | public string Name { get; set; } = string.Empty; 13 | public string Image { get; set; } = string.Empty; 14 | public string Description { get; set; } = string.Empty; 15 | public decimal Price { get; set; } 16 | public int Quantity { get; set; } = 0; 17 | public int Sold { get; set; } = 0; 18 | public decimal Shipping { get; set; } = 0; 19 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 20 | 21 | public Guid CategoryId { get; set; } // Foreign Key for the Category 22 | 23 | [JsonIgnore] 24 | public Category? Category { get; set; } 25 | 26 | [JsonIgnore] 27 | public List OrderProducts { get; set; } = new List(); 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /EFCore/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.Models.orders; 6 | 7 | namespace ecommerce_db_api.EFCore 8 | { 9 | public class User 10 | { 11 | public Guid UserId { get; set; } 12 | public string UserName { get; set; } = string.Empty; 13 | public string Email { get; set; } = string.Empty; 14 | public string Password { get; set; } = string.Empty; 15 | public string? Address { get; set; } = string.Empty; 16 | public string? Image { get; set; } = string.Empty; 17 | public bool IsAdmin { get; set; } = false; 18 | public bool IsBanned { get; set; } = false; 19 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 20 | 21 | public List orders { get; set; } = new List(); 22 | } 23 | } -------------------------------------------------------------------------------- /Mappers/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AutoMapper; 6 | using ecommerce_db_api.EFCore; 7 | using ecommerce_db_api.Models; 8 | using ecommerce_db_api.Models.categories; 9 | using ecommerce_db_api.Models.products; 10 | 11 | namespace ecommerce_db_api.Mappers 12 | { 13 | public class MappingProfile : Profile 14 | { 15 | public MappingProfile() 16 | { 17 | CreateMap(); 18 | CreateMap(); 19 | 20 | CreateMap(); 21 | CreateMap(); 22 | 23 | CreateMap(); 24 | CreateMap(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Migrations/20240930145851_AddProduct.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 8 | using ecommerce_db_api.EFCore; 9 | 10 | #nullable disable 11 | 12 | namespace ecommerce_db_api.Migrations 13 | { 14 | [DbContext(typeof(AppDbContext))] 15 | [Migration("20240930145851_AddProduct")] 16 | partial class AddProduct 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "8.0.8") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 25 | 26 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("ecommerce_db_api.EFCore.Category", b => 29 | { 30 | b.Property("CategoryId") 31 | .ValueGeneratedOnAdd() 32 | .HasColumnType("uuid") 33 | .HasDefaultValueSql("uuid_generate_v4()"); 34 | 35 | b.Property("CreatedAt") 36 | .ValueGeneratedOnAdd() 37 | .HasColumnType("timestamp with time zone") 38 | .HasDefaultValueSql("CURRENT_TIMESTAMP"); 39 | 40 | b.Property("Name") 41 | .IsRequired() 42 | .HasMaxLength(100) 43 | .HasColumnType("character varying(100)"); 44 | 45 | b.Property("Slug") 46 | .IsRequired() 47 | .HasMaxLength(100) 48 | .HasColumnType("character varying(100)"); 49 | 50 | b.HasKey("CategoryId"); 51 | 52 | b.HasIndex("Name") 53 | .IsUnique(); 54 | 55 | b.ToTable("Categories"); 56 | }); 57 | 58 | modelBuilder.Entity("ecommerce_db_api.EFCore.Product", b => 59 | { 60 | b.Property("ProductId") 61 | .ValueGeneratedOnAdd() 62 | .HasColumnType("uuid") 63 | .HasDefaultValueSql("uuid_generate_v4()"); 64 | 65 | b.Property("CategoryId") 66 | .HasColumnType("uuid"); 67 | 68 | b.Property("CreatedAt") 69 | .ValueGeneratedOnAdd() 70 | .HasColumnType("timestamp with time zone") 71 | .HasDefaultValueSql("CURRENT_TIMESTAMP"); 72 | 73 | b.Property("Description") 74 | .IsRequired() 75 | .HasColumnType("text"); 76 | 77 | b.Property("Image") 78 | .IsRequired() 79 | .HasColumnType("text"); 80 | 81 | b.Property("Name") 82 | .IsRequired() 83 | .HasMaxLength(255) 84 | .HasColumnType("character varying(255)"); 85 | 86 | b.Property("Price") 87 | .HasColumnType("numeric"); 88 | 89 | b.Property("Quantity") 90 | .HasColumnType("integer"); 91 | 92 | b.Property("Shipping") 93 | .HasColumnType("numeric"); 94 | 95 | b.Property("Sold") 96 | .HasColumnType("integer"); 97 | 98 | b.HasKey("ProductId"); 99 | 100 | b.HasIndex("CategoryId"); 101 | 102 | b.ToTable("Products"); 103 | }); 104 | 105 | modelBuilder.Entity("ecommerce_db_api.EFCore.User", b => 106 | { 107 | b.Property("UserId") 108 | .ValueGeneratedOnAdd() 109 | .HasColumnType("uuid") 110 | .HasDefaultValueSql("uuid_generate_v4()"); 111 | 112 | b.Property("Address") 113 | .HasMaxLength(255) 114 | .HasColumnType("character varying(255)"); 115 | 116 | b.Property("CreatedAt") 117 | .ValueGeneratedOnAdd() 118 | .HasColumnType("timestamp with time zone") 119 | .HasDefaultValueSql("CURRENT_TIMESTAMP"); 120 | 121 | b.Property("Email") 122 | .IsRequired() 123 | .HasMaxLength(100) 124 | .HasColumnType("character varying(100)"); 125 | 126 | b.Property("Image") 127 | .HasColumnType("text"); 128 | 129 | b.Property("IsAdmin") 130 | .ValueGeneratedOnAdd() 131 | .HasColumnType("boolean") 132 | .HasDefaultValue(false); 133 | 134 | b.Property("IsBanned") 135 | .ValueGeneratedOnAdd() 136 | .HasColumnType("boolean") 137 | .HasDefaultValue(false); 138 | 139 | b.Property("Password") 140 | .IsRequired() 141 | .HasColumnType("text"); 142 | 143 | b.Property("UserName") 144 | .IsRequired() 145 | .HasMaxLength(100) 146 | .HasColumnType("character varying(100)"); 147 | 148 | b.HasKey("UserId"); 149 | 150 | b.HasIndex("Email") 151 | .IsUnique(); 152 | 153 | b.ToTable("Users"); 154 | }); 155 | 156 | modelBuilder.Entity("ecommerce_db_api.EFCore.Product", b => 157 | { 158 | b.HasOne("ecommerce_db_api.EFCore.Category", "Category") 159 | .WithMany("Products") 160 | .HasForeignKey("CategoryId") 161 | .OnDelete(DeleteBehavior.Cascade) 162 | .IsRequired(); 163 | 164 | b.Navigation("Category"); 165 | }); 166 | 167 | modelBuilder.Entity("ecommerce_db_api.EFCore.Category", b => 168 | { 169 | b.Navigation("Products"); 170 | }); 171 | #pragma warning restore 612, 618 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /Migrations/20240930145851_AddProduct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace ecommerce_db_api.Migrations 7 | { 8 | /// 9 | public partial class AddProduct : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.CreateTable( 15 | name: "Categories", 16 | columns: table => new 17 | { 18 | CategoryId = table.Column(type: "uuid", nullable: false, defaultValueSql: "uuid_generate_v4()"), 19 | Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), 20 | Slug = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), 21 | CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") 22 | }, 23 | constraints: table => 24 | { 25 | table.PrimaryKey("PK_Categories", x => x.CategoryId); 26 | }); 27 | 28 | migrationBuilder.CreateTable( 29 | name: "Users", 30 | columns: table => new 31 | { 32 | UserId = table.Column(type: "uuid", nullable: false, defaultValueSql: "uuid_generate_v4()"), 33 | UserName = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), 34 | Email = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), 35 | Password = table.Column(type: "text", nullable: false), 36 | Address = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), 37 | Image = table.Column(type: "text", nullable: true), 38 | IsAdmin = table.Column(type: "boolean", nullable: false, defaultValue: false), 39 | IsBanned = table.Column(type: "boolean", nullable: false, defaultValue: false), 40 | CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") 41 | }, 42 | constraints: table => 43 | { 44 | table.PrimaryKey("PK_Users", x => x.UserId); 45 | }); 46 | 47 | migrationBuilder.CreateTable( 48 | name: "Products", 49 | columns: table => new 50 | { 51 | ProductId = table.Column(type: "uuid", nullable: false, defaultValueSql: "uuid_generate_v4()"), 52 | Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), 53 | Image = table.Column(type: "text", nullable: false), 54 | Description = table.Column(type: "text", nullable: false), 55 | Price = table.Column(type: "numeric", nullable: false), 56 | Quantity = table.Column(type: "integer", nullable: false), 57 | Sold = table.Column(type: "integer", nullable: false), 58 | Shipping = table.Column(type: "numeric", nullable: false), 59 | CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), 60 | CategoryId = table.Column(type: "uuid", nullable: false) 61 | }, 62 | constraints: table => 63 | { 64 | table.PrimaryKey("PK_Products", x => x.ProductId); 65 | table.ForeignKey( 66 | name: "FK_Products_Categories_CategoryId", 67 | column: x => x.CategoryId, 68 | principalTable: "Categories", 69 | principalColumn: "CategoryId", 70 | onDelete: ReferentialAction.Cascade); 71 | }); 72 | 73 | migrationBuilder.CreateIndex( 74 | name: "IX_Categories_Name", 75 | table: "Categories", 76 | column: "Name", 77 | unique: true); 78 | 79 | migrationBuilder.CreateIndex( 80 | name: "IX_Products_CategoryId", 81 | table: "Products", 82 | column: "CategoryId"); 83 | 84 | migrationBuilder.CreateIndex( 85 | name: "IX_Users_Email", 86 | table: "Users", 87 | column: "Email", 88 | unique: true); 89 | } 90 | 91 | /// 92 | protected override void Down(MigrationBuilder migrationBuilder) 93 | { 94 | migrationBuilder.DropTable( 95 | name: "Products"); 96 | 97 | migrationBuilder.DropTable( 98 | name: "Users"); 99 | 100 | migrationBuilder.DropTable( 101 | name: "Categories"); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Migrations/AppDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 7 | using ecommerce_db_api.EFCore; 8 | 9 | #nullable disable 10 | 11 | namespace ecommerce_db_api.Migrations 12 | { 13 | [DbContext(typeof(AppDbContext))] 14 | partial class AppDbContextModelSnapshot : ModelSnapshot 15 | { 16 | protected override void BuildModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "8.0.8") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 22 | 23 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 24 | 25 | modelBuilder.Entity("ecommerce_db_api.EFCore.Category", b => 26 | { 27 | b.Property("CategoryId") 28 | .ValueGeneratedOnAdd() 29 | .HasColumnType("uuid") 30 | .HasDefaultValueSql("uuid_generate_v4()"); 31 | 32 | b.Property("CreatedAt") 33 | .ValueGeneratedOnAdd() 34 | .HasColumnType("timestamp with time zone") 35 | .HasDefaultValueSql("CURRENT_TIMESTAMP"); 36 | 37 | b.Property("Name") 38 | .IsRequired() 39 | .HasMaxLength(100) 40 | .HasColumnType("character varying(100)"); 41 | 42 | b.Property("Slug") 43 | .IsRequired() 44 | .HasMaxLength(100) 45 | .HasColumnType("character varying(100)"); 46 | 47 | b.HasKey("CategoryId"); 48 | 49 | b.HasIndex("Name") 50 | .IsUnique(); 51 | 52 | b.ToTable("Categories"); 53 | }); 54 | 55 | modelBuilder.Entity("ecommerce_db_api.EFCore.Product", b => 56 | { 57 | b.Property("ProductId") 58 | .ValueGeneratedOnAdd() 59 | .HasColumnType("uuid") 60 | .HasDefaultValueSql("uuid_generate_v4()"); 61 | 62 | b.Property("CategoryId") 63 | .HasColumnType("uuid"); 64 | 65 | b.Property("CreatedAt") 66 | .ValueGeneratedOnAdd() 67 | .HasColumnType("timestamp with time zone") 68 | .HasDefaultValueSql("CURRENT_TIMESTAMP"); 69 | 70 | b.Property("Description") 71 | .IsRequired() 72 | .HasColumnType("text"); 73 | 74 | b.Property("Image") 75 | .IsRequired() 76 | .HasColumnType("text"); 77 | 78 | b.Property("Name") 79 | .IsRequired() 80 | .HasMaxLength(255) 81 | .HasColumnType("character varying(255)"); 82 | 83 | b.Property("Price") 84 | .HasColumnType("numeric"); 85 | 86 | b.Property("Quantity") 87 | .HasColumnType("integer"); 88 | 89 | b.Property("Shipping") 90 | .HasColumnType("numeric"); 91 | 92 | b.Property("Sold") 93 | .HasColumnType("integer"); 94 | 95 | b.HasKey("ProductId"); 96 | 97 | b.HasIndex("CategoryId"); 98 | 99 | b.ToTable("Products"); 100 | }); 101 | 102 | modelBuilder.Entity("ecommerce_db_api.EFCore.User", b => 103 | { 104 | b.Property("UserId") 105 | .ValueGeneratedOnAdd() 106 | .HasColumnType("uuid") 107 | .HasDefaultValueSql("uuid_generate_v4()"); 108 | 109 | b.Property("Address") 110 | .HasMaxLength(255) 111 | .HasColumnType("character varying(255)"); 112 | 113 | b.Property("CreatedAt") 114 | .ValueGeneratedOnAdd() 115 | .HasColumnType("timestamp with time zone") 116 | .HasDefaultValueSql("CURRENT_TIMESTAMP"); 117 | 118 | b.Property("Email") 119 | .IsRequired() 120 | .HasMaxLength(100) 121 | .HasColumnType("character varying(100)"); 122 | 123 | b.Property("Image") 124 | .HasColumnType("text"); 125 | 126 | b.Property("IsAdmin") 127 | .ValueGeneratedOnAdd() 128 | .HasColumnType("boolean") 129 | .HasDefaultValue(false); 130 | 131 | b.Property("IsBanned") 132 | .ValueGeneratedOnAdd() 133 | .HasColumnType("boolean") 134 | .HasDefaultValue(false); 135 | 136 | b.Property("Password") 137 | .IsRequired() 138 | .HasColumnType("text"); 139 | 140 | b.Property("UserName") 141 | .IsRequired() 142 | .HasMaxLength(100) 143 | .HasColumnType("character varying(100)"); 144 | 145 | b.HasKey("UserId"); 146 | 147 | b.HasIndex("Email") 148 | .IsUnique(); 149 | 150 | b.ToTable("Users"); 151 | }); 152 | 153 | modelBuilder.Entity("ecommerce_db_api.EFCore.Product", b => 154 | { 155 | b.HasOne("ecommerce_db_api.EFCore.Category", "Category") 156 | .WithMany("Products") 157 | .HasForeignKey("CategoryId") 158 | .OnDelete(DeleteBehavior.Cascade) 159 | .IsRequired(); 160 | 161 | b.Navigation("Category"); 162 | }); 163 | 164 | modelBuilder.Entity("ecommerce_db_api.EFCore.Category", b => 165 | { 166 | b.Navigation("Products"); 167 | }); 168 | #pragma warning restore 612, 618 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /Models/categories/CategoryDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.Models.categories 7 | { 8 | public class CategoryDto 9 | { 10 | public Guid CategoryId { get; set; } 11 | public string? Name { get; set; } 12 | public string? Slug { get; set; } 13 | public DateTime CreatedAt { get; set; } 14 | 15 | // 1-Many relationship => 1 category has multiple products 16 | // One-to-Many: A category has many products 17 | // public List Products { get; set; } = new List(); 18 | } 19 | } -------------------------------------------------------------------------------- /Models/categories/CreateCategoryDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace ecommerce_db_api.Models 8 | { 9 | public class CreateCategoryDto 10 | { 11 | 12 | [Required(ErrorMessage = "CategoryName is missing.")] 13 | [StringLength(100, ErrorMessage = "CategoryName must be between 3 and 100 characters.", MinimumLength = 3)] 14 | public string Name { get; set; } 15 | public string? Slug { get; set; } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /Models/orders/CreateOrderDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.Models.orders 7 | { 8 | public class CreateOrderDto 9 | { 10 | public Guid UserId { get; set; } 11 | public List OrderProducts { get; set; } = new List(); 12 | } 13 | } -------------------------------------------------------------------------------- /Models/orders/CreateOrderProductDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.Models.orders 7 | { 8 | public class CreateOrderProductDto 9 | { 10 | public Guid ProductId { get; set; } 11 | public int Quantity { get; set; } 12 | public decimal Price { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Models/orders/OrderDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.Models.orders 7 | { 8 | public class OrderDto 9 | { 10 | public Guid OrderId { get; set; } 11 | public DateTime OrderDate { get; set; } 12 | public Guid UserId { get; set; } 13 | public List OrderProducts { get; set; } = new List(); 14 | } 15 | } -------------------------------------------------------------------------------- /Models/orders/OrderProductDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.Models.orders 7 | { 8 | public class OrderProductDto 9 | { 10 | public Guid ProductId { get; set; } 11 | public int Quantity { get; set; } 12 | public decimal Price { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Models/products/CreateProdutDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace ecommerce_db_api.Models.products 8 | { 9 | public class CreateProdutDto 10 | { 11 | 12 | [Required] 13 | public string Name { get; set; } 14 | 15 | public string Image { get; set; } = string.Empty; 16 | public string Description { get; set; } = string.Empty; 17 | 18 | [Required] 19 | public decimal Price { get; set; } 20 | 21 | [Required] 22 | public int Quantity { get; set; } 23 | 24 | public int Sold { get; set; } = 0; 25 | 26 | public decimal Shipping { get; set; } = 0; 27 | 28 | [Required] 29 | public Guid CategoryId { get; set; } // Foreign Key for the Category 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /Models/products/ProductDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ecommerce_db_api.EFCore; 6 | 7 | namespace ecommerce_db_api.Models.products 8 | { 9 | public class ProductDto 10 | { 11 | public Guid ProductId { get; set; } 12 | public string Name { get; set; } 13 | public string Image { get; set; } 14 | public string Description { get; set; } 15 | public decimal Price { get; set; } 16 | public int Quantity { get; set; } 17 | public int Sold { get; set; } 18 | public decimal Shipping { get; set; } 19 | public DateTime CreatedAt { get; set; } 20 | public Category? Category { get; set; } 21 | public Guid CategoryId { get; set; } // Foreign Key for the Category 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /Models/users/CreateUserDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace ecommerce_db_api.Models 8 | { 9 | public class CreateUserDto 10 | { 11 | 12 | [Required(ErrorMessage = "Username is missing.")] 13 | [StringLength(50, ErrorMessage = "Username must be between 3 and 50 characters.", MinimumLength = 3)] 14 | public string UserName { get; set; } = string.Empty; 15 | 16 | [Required(ErrorMessage = "Email is required.")] 17 | [EmailAddress(ErrorMessage = "Invalid Email Address.")] 18 | public string Email { get; set; } = string.Empty; 19 | 20 | [Required(ErrorMessage = "Password is required.")] 21 | [StringLength(100, ErrorMessage = "Password must be between 6 and 100 characters.", MinimumLength = 6)] 22 | public string Password { get; set; } = string.Empty; 23 | 24 | [StringLength(255, ErrorMessage = "Address can't exceed 255 characters.")] 25 | public string? Address { get; set; } 26 | 27 | // [Url(ErrorMessage = "Invalid URL format for Image.")] 28 | public string? Image { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /Models/users/UpdateUserDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace ecommerce_db_api.Models 8 | { 9 | public class UpdateUserDto 10 | { 11 | 12 | [StringLength(50, ErrorMessage = "Username must be between 3 and 50 characters.", MinimumLength = 3)] 13 | public string? UserName { get; set; } 14 | 15 | [StringLength(100, ErrorMessage = "Password must be between 6 and 100 characters.", MinimumLength = 6)] 16 | public string? Password { get; set; } 17 | 18 | [StringLength(255, ErrorMessage = "Address can't exceed 255 characters.")] 19 | public string? Address { get; set; } 20 | 21 | public string? Image { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /Models/users/UserDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ecommerce_db_api.Models 7 | { 8 | public class UserDto 9 | { 10 | public Guid UserId { get; set; } 11 | public string UserName { get; set; } 12 | public string Email { get; set; } 13 | public string? Address { get; set; } 14 | public string? Image { get; set; } 15 | public bool IsAdmin { get; set; } 16 | public bool IsBanned { get; set; } 17 | public DateTime CreatedAt { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using ecommerce_db_api.EFCore; 2 | using ecommerce_db_api.Services; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | var builder = WebApplication.CreateBuilder(args); 6 | 7 | builder.Services.AddAutoMapper(typeof(Program)); 8 | 9 | builder.Services.AddControllers() 10 | .ConfigureApiBehaviorOptions(options => 11 | { 12 | options.SuppressModelStateInvalidFilter = true; // Disable automatic model validation response 13 | }); 14 | builder.Services.AddControllers(); 15 | // builder.Services.AddControllers() 16 | // .AddJsonOptions(options => 17 | // { 18 | // options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve; 19 | // options.JsonSerializerOptions.WriteIndented = true; 20 | // }); 21 | builder.Services.AddScoped(); 22 | builder.Services.AddScoped(); 23 | builder.Services.AddScoped(); 24 | builder.Services.AddEndpointsApiExplorer(); 25 | builder.Services.AddSwaggerGen(); 26 | builder.Services.AddDbContext(options => 27 | options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); 28 | 29 | var app = builder.Build(); 30 | 31 | // Configure the HTTP request pipeline. 32 | if (app.Environment.IsDevelopment()) 33 | { 34 | app.UseSwagger(); 35 | app.UseSwaggerUI(); 36 | } 37 | 38 | app.UseHttpsRedirection(); 39 | 40 | 41 | app.MapGet("/", () => 42 | { 43 | var response = new { Success = true, Message = "Api is running" }; 44 | return Results.Ok(response); 45 | }) 46 | .WithOpenApi(); 47 | 48 | app.MapControllers(); 49 | app.Run(); 50 | -------------------------------------------------------------------------------- /Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:22907", 8 | "sslPort": 44321 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": false, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5234", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": false, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7080;http://localhost:5234", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Services/CategoryService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using ecommerce_db_api.EFCore; 8 | using ecommerce_db_api.Models; 9 | using ecommerce_db_api.Models.categories; 10 | using Microsoft.EntityFrameworkCore; 11 | 12 | namespace ecommerce_db_api.Services 13 | { 14 | public class CategoryService 15 | { 16 | private readonly AppDbContext _appDbContext; 17 | private readonly IMapper _mapper; 18 | 19 | public CategoryService(AppDbContext appDbContext, IMapper mapper) 20 | { 21 | _appDbContext = appDbContext; 22 | _mapper = mapper; 23 | } 24 | 25 | public async Task CreateCategoryServiceAsync(CreateCategoryDto newCategory) 26 | { 27 | try 28 | { 29 | 30 | // create the slug here 31 | var slug = newCategory.Name.Replace(" ", "-"); 32 | newCategory.Slug = slug; 33 | 34 | var category = _mapper.Map(newCategory); 35 | await _appDbContext.AddAsync(category); 36 | await _appDbContext.SaveChangesAsync(); 37 | return category; 38 | } 39 | catch (DbUpdateException dbEx) 40 | { 41 | // Handle database update exceptions (like unique constraint violations) 42 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 43 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 44 | } 45 | catch (Exception ex) 46 | { 47 | // Handle any other unexpected exceptions 48 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 49 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 50 | } 51 | } 52 | 53 | public async Task> GetCategoryServiceAsync() 54 | { 55 | try 56 | { 57 | var categories = await _appDbContext.Categories.ToListAsync(); 58 | var categoriesData = _mapper.Map>(categories); 59 | return categoriesData; 60 | } 61 | catch (DbUpdateException dbEx) 62 | { 63 | // Handle database update exceptions (like unique constraint violations) 64 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 65 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 66 | } 67 | catch (Exception ex) 68 | { 69 | // Handle any other unexpected exceptions 70 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 71 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 72 | } 73 | } 74 | 75 | // public async Task GetUserServiceByIdAsync(Guid userId) 76 | // { 77 | // try 78 | // { 79 | // var user = await _appDbContext.Users.FindAsync(userId); 80 | // if (user == null) 81 | // { 82 | // return null; 83 | // } 84 | // // User Model to UserDto 85 | // // User Model to UserDto 86 | // var userData = _mapper.Map(user); 87 | // return userData; 88 | // } 89 | // catch (DbUpdateException dbEx) 90 | // { 91 | // // Handle database update exceptions (like unique constraint violations) 92 | // Console.WriteLine($"Database Update Error: {dbEx.Message}"); 93 | // throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 94 | // } 95 | // catch (Exception ex) 96 | // { 97 | // // Handle any other unexpected exceptions 98 | // Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 99 | // throw new ApplicationException("An unexpected error occurred. Please try again later."); 100 | // } 101 | // } 102 | // public async Task DeleteUserServiceByIdAsync(Guid userId) 103 | // { 104 | // try 105 | // { 106 | // var user = await _appDbContext.Users.FindAsync(userId); 107 | // if (user == null) 108 | // { 109 | // return false; 110 | // } 111 | // _appDbContext.Users.Remove(user); 112 | // await _appDbContext.SaveChangesAsync(); 113 | // return true; 114 | // } 115 | // catch (DbUpdateException dbEx) 116 | // { 117 | // // Handle database update exceptions (like unique constraint violations) 118 | // Console.WriteLine($"Database Update Error: {dbEx.Message}"); 119 | // throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 120 | // } 121 | // catch (Exception ex) 122 | // { 123 | // // Handle any other unexpected exceptions 124 | // Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 125 | // throw new ApplicationException("An unexpected error occurred. Please try again later."); 126 | // } 127 | // } 128 | 129 | // public async Task UpdateUserServiceAsync(UpdateUserDto updateUser, Guid userId) 130 | // { 131 | // try 132 | // { 133 | // var user = await _appDbContext.Users.FindAsync(userId); 134 | // if (user == null) 135 | // { 136 | // return null; 137 | // } 138 | 139 | // user.UserName = updateUser.UserName ?? user.UserName; 140 | 141 | // if (updateUser.Password != null) 142 | // { 143 | // user.Password = BCrypt.Net.BCrypt.HashPassword(updateUser.Password) ?? user.Password; 144 | // } 145 | 146 | // user.Address = updateUser.Address ?? user.Address; 147 | // user.Image = updateUser.Image ?? user.Image; 148 | 149 | // _appDbContext.Update(user); 150 | // await _appDbContext.SaveChangesAsync(); 151 | 152 | // // User Model to UserDto 153 | // var usersData = _mapper.Map(user); 154 | // return usersData; 155 | // } 156 | // catch (DbUpdateException dbEx) 157 | // { 158 | // // Handle database update exceptions (like unique constraint violations) 159 | // Console.WriteLine($"Database Update Error: {dbEx.Message}"); 160 | // throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 161 | // } 162 | // catch (Exception ex) 163 | // { 164 | // // Handle any other unexpected exceptions 165 | // Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 166 | // throw new ApplicationException("An unexpected error occurred. Please try again later."); 167 | // } 168 | // } 169 | 170 | 171 | } 172 | } -------------------------------------------------------------------------------- /Services/OrderService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AutoMapper; 6 | using ecommerce_db_api.EFCore; 7 | using ecommerce_db_api.Models.orders; 8 | using Microsoft.EntityFrameworkCore; 9 | 10 | namespace ecommerce_db_api.Services 11 | { 12 | public interface IOrderService 13 | { 14 | Task CreateOrderAsync(CreateOrderDto createOrderDto); 15 | Task GetOrderByIdAsync(Guid orderId); 16 | Task UpdateOrderAsync(Guid orderId, CreateOrderDto updateOrderDto); 17 | Task DeleteOrderByIdAsync(Guid orderId); 18 | } 19 | public class OrderService 20 | { 21 | private readonly AppDbContext _appDbContext; 22 | private readonly IMapper _mapper; 23 | 24 | public OrderService(AppDbContext appDbContext, IMapper mapper) 25 | { 26 | _appDbContext = appDbContext; 27 | _mapper = mapper; 28 | } 29 | 30 | // Create a new order 31 | public async Task CreateOrderAsync(CreateOrderDto createOrderDto) 32 | { 33 | var order = new Order 34 | { 35 | UserId = createOrderDto.UserId, 36 | OrderDate = DateTime.UtcNow 37 | }; 38 | 39 | foreach (var orderProductDto in createOrderDto.OrderProducts) 40 | { 41 | var orderProduct = new OrderProduct 42 | { 43 | ProductId = orderProductDto.ProductId, 44 | Quantity = orderProductDto.Quantity, 45 | Price = orderProductDto.Price 46 | }; 47 | 48 | order.OrderProducts.Add(orderProduct); 49 | } 50 | 51 | await _appDbContext.Orders.AddAsync(order); 52 | await _appDbContext.SaveChangesAsync(); 53 | 54 | var orderDto = _mapper.Map(order); 55 | return orderDto; 56 | } 57 | 58 | // Get order by ID 59 | public async Task GetOrderByIdAsync(Guid orderId) 60 | { 61 | var order = await _appDbContext.Orders 62 | .Include(o => o.OrderProducts) 63 | .ThenInclude(op => op.Product) // Include Product details 64 | .Include(o => o.User) // Include User details 65 | .FirstOrDefaultAsync(o => o.OrderId == orderId); 66 | 67 | if (order == null) 68 | return null; 69 | 70 | return _mapper.Map(order); 71 | } 72 | 73 | // Update an order 74 | public async Task UpdateOrderAsync(Guid orderId, CreateOrderDto updateOrderDto) 75 | { 76 | var order = await _appDbContext.Orders 77 | .Include(o => o.OrderProducts) 78 | .FirstOrDefaultAsync(o => o.OrderId == orderId); 79 | 80 | if (order == null) 81 | return null; 82 | 83 | // Clear existing products and add updated products 84 | order.OrderProducts.Clear(); 85 | foreach (var orderProductDto in updateOrderDto.OrderProducts) 86 | { 87 | var orderProduct = new OrderProduct 88 | { 89 | ProductId = orderProductDto.ProductId, 90 | Quantity = orderProductDto.Quantity, 91 | Price = orderProductDto.Price 92 | }; 93 | 94 | order.OrderProducts.Add(orderProduct); 95 | } 96 | 97 | _appDbContext.Orders.Update(order); 98 | await _appDbContext.SaveChangesAsync(); 99 | 100 | return _mapper.Map(order); 101 | } 102 | 103 | // Delete an order by ID 104 | public async Task DeleteOrderByIdAsync(Guid orderId) 105 | { 106 | var order = await _appDbContext.Orders 107 | .Include(o => o.OrderProducts) 108 | .FirstOrDefaultAsync(o => o.OrderId == orderId); 109 | 110 | if (order == null) 111 | return false; 112 | 113 | _appDbContext.Orders.Remove(order); 114 | await _appDbContext.SaveChangesAsync(); 115 | return true; 116 | } 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /Services/ProductService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using ecommerce_db_api.EFCore; 8 | using ecommerce_db_api.Models; 9 | using ecommerce_db_api.Models.categories; 10 | using ecommerce_db_api.Models.products; 11 | using Microsoft.EntityFrameworkCore; 12 | using Newtonsoft.Json; 13 | 14 | namespace ecommerce_db_api.Services 15 | { 16 | public class ProductService 17 | { 18 | private readonly AppDbContext _appDbContext; 19 | private readonly IMapper _mapper; 20 | 21 | public ProductService(AppDbContext appDbContext, IMapper mapper) 22 | { 23 | _appDbContext = appDbContext; 24 | _mapper = mapper; 25 | } 26 | 27 | public async Task CreateProductServiceAsync(CreateProdutDto newProduct) 28 | { 29 | try 30 | { 31 | var product = _mapper.Map(newProduct); 32 | await _appDbContext.Products.AddAsync(product); 33 | await _appDbContext.SaveChangesAsync(); 34 | // product entity here => Product Dto 35 | var productData = _mapper.Map(product); 36 | return productData; 37 | } 38 | catch (DbUpdateException dbEx) 39 | { 40 | // Handle database update exceptions (like unique constraint violations) 41 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 42 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 43 | } 44 | catch (Exception ex) 45 | { 46 | // Handle any other unexpected exceptions 47 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 48 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 49 | } 50 | } 51 | 52 | public async Task> GetProductsServiceAsync() 53 | { 54 | try 55 | { 56 | Console.WriteLine($"----------test2---------"); 57 | 58 | var products = await _appDbContext.Products.Include(p => p.Category).ToListAsync(); 59 | Console.WriteLine($"----------test3---------"); 60 | 61 | var productsData = _mapper.Map>(products); 62 | 63 | Console.WriteLine($"----------test4---------"); 64 | 65 | return productsData; 66 | } 67 | catch (DbUpdateException dbEx) 68 | { 69 | // Handle database update exceptions (like unique constraint violations) 70 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 71 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 72 | } 73 | catch (Exception ex) 74 | { 75 | // Handle any other unexpected exceptions 76 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 77 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 78 | } 79 | } 80 | 81 | // // public async Task GetUserServiceByIdAsync(Guid userId) 82 | // { 83 | // try 84 | // { 85 | // var user = await _appDbContext.Users.FindAsync(userId); 86 | // if (user == null) 87 | // { 88 | // return null; 89 | // } 90 | // // User Model to UserDto 91 | // // User Model to UserDto 92 | // var userData = _mapper.Map(user); 93 | // return userData; 94 | // } 95 | // catch (DbUpdateException dbEx) 96 | // { 97 | // // Handle database update exceptions (like unique constraint violations) 98 | // Console.WriteLine($"Database Update Error: {dbEx.Message}"); 99 | // throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 100 | // } 101 | // catch (Exception ex) 102 | // { 103 | // // Handle any other unexpected exceptions 104 | // Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 105 | // throw new ApplicationException("An unexpected error occurred. Please try again later."); 106 | // } 107 | // } 108 | // public async Task DeleteUserServiceByIdAsync(Guid userId) 109 | // { 110 | // try 111 | // { 112 | // var user = await _appDbContext.Users.FindAsync(userId); 113 | // if (user == null) 114 | // { 115 | // return false; 116 | // } 117 | // _appDbContext.Users.Remove(user); 118 | // await _appDbContext.SaveChangesAsync(); 119 | // return true; 120 | // } 121 | // catch (DbUpdateException dbEx) 122 | // { 123 | // // Handle database update exceptions (like unique constraint violations) 124 | // Console.WriteLine($"Database Update Error: {dbEx.Message}"); 125 | // throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 126 | // } 127 | // catch (Exception ex) 128 | // { 129 | // // Handle any other unexpected exceptions 130 | // Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 131 | // throw new ApplicationException("An unexpected error occurred. Please try again later."); 132 | // } 133 | // } 134 | 135 | // public async Task UpdateUserServiceAsync(UpdateUserDto updateUser, Guid userId) 136 | // { 137 | // try 138 | // { 139 | // var user = await _appDbContext.Users.FindAsync(userId); 140 | // if (user == null) 141 | // { 142 | // return null; 143 | // } 144 | 145 | // user.UserName = updateUser.UserName ?? user.UserName; 146 | 147 | // if (updateUser.Password != null) 148 | // { 149 | // user.Password = BCrypt.Net.BCrypt.HashPassword(updateUser.Password) ?? user.Password; 150 | // } 151 | 152 | // user.Address = updateUser.Address ?? user.Address; 153 | // user.Image = updateUser.Image ?? user.Image; 154 | 155 | // _appDbContext.Update(user); 156 | // await _appDbContext.SaveChangesAsync(); 157 | 158 | // // User Model to UserDto 159 | // var usersData = _mapper.Map(user); 160 | // return usersData; 161 | // } 162 | // catch (DbUpdateException dbEx) 163 | // { 164 | // // Handle database update exceptions (like unique constraint violations) 165 | // Console.WriteLine($"Database Update Error: {dbEx.Message}"); 166 | // throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 167 | // } 168 | // catch (Exception ex) 169 | // { 170 | // // Handle any other unexpected exceptions 171 | // Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 172 | // throw new ApplicationException("An unexpected error occurred. Please try again later."); 173 | // } 174 | // } 175 | 176 | 177 | } 178 | } -------------------------------------------------------------------------------- /Services/UserService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoMapper; 7 | using ecommerce_db_api.EFCore; 8 | using ecommerce_db_api.Models; 9 | using Microsoft.EntityFrameworkCore; 10 | 11 | namespace ecommerce_db_api.Services 12 | { 13 | public class UserService 14 | { 15 | private readonly AppDbContext _appDbContext; 16 | private readonly IMapper _mapper; 17 | 18 | public UserService(AppDbContext appDbContext, IMapper mapper) 19 | { 20 | _appDbContext = appDbContext; 21 | _mapper = mapper; 22 | } 23 | 24 | public async Task CreateUserServiceAsync(CreateUserDto newUser) 25 | { 26 | try 27 | { 28 | var hashedPassword = BCrypt.Net.BCrypt.HashPassword(newUser.Password); 29 | newUser.Password = hashedPassword; 30 | // CreateUserDto convert to User Entity 31 | var user = _mapper.Map(newUser); 32 | await _appDbContext.AddAsync(user); 33 | await _appDbContext.SaveChangesAsync(); 34 | return user; 35 | } 36 | catch (DbUpdateException dbEx) 37 | { 38 | // Handle database update exceptions (like unique constraint violations) 39 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 40 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 41 | } 42 | catch (Exception ex) 43 | { 44 | // Handle any other unexpected exceptions 45 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 46 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 47 | } 48 | } 49 | 50 | public async Task> GetUsersServiceAsync() 51 | { 52 | try 53 | { 54 | var users = await _appDbContext.Users.ToListAsync(); 55 | var usersData = _mapper.Map>(users); 56 | return usersData; 57 | } 58 | catch (DbUpdateException dbEx) 59 | { 60 | // Handle database update exceptions (like unique constraint violations) 61 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 62 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 63 | } 64 | catch (Exception ex) 65 | { 66 | // Handle any other unexpected exceptions 67 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 68 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 69 | } 70 | } 71 | 72 | public async Task GetUserServiceByIdAsync(Guid userId) 73 | { 74 | try 75 | { 76 | var user = await _appDbContext.Users.FindAsync(userId); 77 | if (user == null) 78 | { 79 | return null; 80 | } 81 | // User Model to UserDto 82 | // User Model to UserDto 83 | var userData = _mapper.Map(user); 84 | return userData; 85 | } 86 | catch (DbUpdateException dbEx) 87 | { 88 | // Handle database update exceptions (like unique constraint violations) 89 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 90 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 91 | } 92 | catch (Exception ex) 93 | { 94 | // Handle any other unexpected exceptions 95 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 96 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 97 | } 98 | } 99 | public async Task DeleteUserServiceByIdAsync(Guid userId) 100 | { 101 | try 102 | { 103 | var user = await _appDbContext.Users.FindAsync(userId); 104 | if (user == null) 105 | { 106 | return false; 107 | } 108 | _appDbContext.Users.Remove(user); 109 | await _appDbContext.SaveChangesAsync(); 110 | return true; 111 | } 112 | catch (DbUpdateException dbEx) 113 | { 114 | // Handle database update exceptions (like unique constraint violations) 115 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 116 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 117 | } 118 | catch (Exception ex) 119 | { 120 | // Handle any other unexpected exceptions 121 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 122 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 123 | } 124 | } 125 | 126 | public async Task UpdateUserServiceAsync(UpdateUserDto updateUser, Guid userId) 127 | { 128 | try 129 | { 130 | var user = await _appDbContext.Users.FindAsync(userId); 131 | if (user == null) 132 | { 133 | return null; 134 | } 135 | 136 | user.UserName = updateUser.UserName ?? user.UserName; 137 | 138 | if (updateUser.Password != null) 139 | { 140 | user.Password = BCrypt.Net.BCrypt.HashPassword(updateUser.Password) ?? user.Password; 141 | } 142 | 143 | user.Address = updateUser.Address ?? user.Address; 144 | user.Image = updateUser.Image ?? user.Image; 145 | 146 | _appDbContext.Update(user); 147 | await _appDbContext.SaveChangesAsync(); 148 | 149 | // User Model to UserDto 150 | var usersData = _mapper.Map(user); 151 | return usersData; 152 | } 153 | catch (DbUpdateException dbEx) 154 | { 155 | // Handle database update exceptions (like unique constraint violations) 156 | Console.WriteLine($"Database Update Error: {dbEx.Message}"); 157 | throw new ApplicationException("An error occurred while saving to the database. Please check the data and try again."); 158 | } 159 | catch (Exception ex) 160 | { 161 | // Handle any other unexpected exceptions 162 | Console.WriteLine($"An unexpected error occurred: {ex.Message}"); 163 | throw new ApplicationException("An unexpected error occurred. Please try again later."); 164 | } 165 | } 166 | 167 | 168 | } 169 | } -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "ConnectionStrings": { 10 | "DefaultConnection": "Server=localhost;Port=5432;Database=sda3_ecommerce;Username=postgres;Password=new_password;" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ecommerce-db-api.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | ecommerce_db_api 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | all 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ecommerce-db-api.http: -------------------------------------------------------------------------------- 1 | @ecommerce_db_api_HostAddress = http://localhost:5234 2 | 3 | GET {{ecommerce_db_api_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | 8 | GET http://localhost:5234 9 | 10 | ### 11 | 12 | GET http://localhost:5234/api/users 13 | 14 | ### 15 | 16 | GET http://localhost:5234/api/users/91d6557d-4623-43e1-9a5a-4e2b480b4d05 17 | 18 | ### 19 | 20 | DELETE http://localhost:5234/api/users/cb8966c9-8331-43f2-b441-96aa48c5b88e 21 | 22 | ### 23 | 24 | POST http://localhost:5234/api/users 25 | Content-Type: application/json 26 | 27 | { 28 | "userName" : "test5", 29 | "Email" : "test5@gmail.com", 30 | "Password" : "123456" 31 | } 32 | 33 | ### 34 | 35 | PUT http://localhost:5234/api/users/c2dc333b-0a31-4c20-80c4-ee3644201c17 36 | Content-Type: application/json 37 | 38 | { 39 | "userName" : "alex" 40 | } 41 | 42 | ### 43 | 44 | GET http://localhost:5234/api/categories 45 | 46 | ### 47 | 48 | POST http://localhost:5234/api/categories 49 | Content-Type: application/json 50 | 51 | { 52 | "name": "Electronics", 53 | "description": "Devices and gadgets including phones, laptops, and other electronic equipment" 54 | } 55 | 56 | ### 57 | 58 | POST http://localhost:5234/api/products 59 | Content-Type: application/json 60 | 61 | { 62 | "name": "Mens Cotton Jacket 2", 63 | "price": 55.99, 64 | "description": "great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors. Good gift choice for you or your family member. A warm hearted love to Father, husband or son in this thanksgiving or Christmas Day.", 65 | "image": "https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg", 66 | "quantity": 12, 67 | "shipping": 0, 68 | "categoryId": "84be1b97-1ef0-4012-9def-da973b2428e5" 69 | } 70 | 71 | ### 72 | 73 | GET http://localhost:5234/api/products -------------------------------------------------------------------------------- /ecommerce-db-api.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ecommerce-db-api", "ecommerce-db-api.csproj", "{A71A724B-F19D-47AB-A447-434DF739B710}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A71A724B-F19D-47AB-A447-434DF739B710}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A71A724B-F19D-47AB-A447-434DF739B710}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A71A724B-F19D-47AB-A447-434DF739B710}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A71A724B-F19D-47AB-A447-434DF739B710}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {9338BF26-D6D1-485C-B308-9665ABB2C053} 24 | EndGlobalSection 25 | EndGlobal 26 | --------------------------------------------------------------------------------