From f8ca672bc64ec3b0c5afcd3519569dbb48e81e2f Mon Sep 17 00:00:00 2001 From: javadnezamdost Date: Sat, 29 Nov 2025 20:52:45 +0400 Subject: [PATCH] feat:Category --- .../Categorys/CategorysApplication.cs | 94 +++++++++++++++++++ .../Categorys/ViewModels/CategoryViewModel.cs | 6 ++ .../ViewModels/CreateCategoryViewModel.cs | 13 +++ .../ViewModels/UpdateCategoryViewModel.cs | 6 ++ .../Domain/Aggregates/Categorys/Category.cs | 46 +++++++++ .../Categorys/Data/ICategoryRepository.cs | 10 ++ .../Persistence/DatabaseContext.cs | 2 + .../Categorys/CategoryRepository.cs | 51 ++++++++++ src/Presentation/Server/Pages/Index.cshtml | 1 + .../Server/Pages/Panel/Category/Create.cshtml | 37 ++++++++ .../Pages/Panel/Category/Create.cshtml.cs | 28 ++++++ .../Server/Pages/Panel/Category/Delete.cshtml | 37 ++++++++ .../Pages/Panel/Category/Delete.cshtml.cs | 37 ++++++++ .../Server/Pages/Panel/Category/Index.cshtml | 33 +++++++ .../Pages/Panel/Category/Index.cshtml.cs | 15 +++ .../Server/Pages/Panel/Category/Update.cshtml | 38 ++++++++ .../Pages/Panel/Category/Update.cshtml.cs | 43 +++++++++ src/Presentation/Server/Program.cs | 6 ++ 18 files changed, 503 insertions(+) create mode 100644 src/Core/Application/Aggregates/Categorys/CategorysApplication.cs create mode 100644 src/Core/Application/Aggregates/Categorys/ViewModels/CategoryViewModel.cs create mode 100644 src/Core/Application/Aggregates/Categorys/ViewModels/CreateCategoryViewModel.cs create mode 100644 src/Core/Application/Aggregates/Categorys/ViewModels/UpdateCategoryViewModel.cs create mode 100644 src/Core/Domain/Aggregates/Categorys/Category.cs create mode 100644 src/Core/Domain/Aggregates/Categorys/Data/ICategoryRepository.cs create mode 100644 src/Persistence/Persistence/Repositories/Aggregates/Categorys/CategoryRepository.cs create mode 100644 src/Presentation/Server/Pages/Panel/Category/Create.cshtml create mode 100644 src/Presentation/Server/Pages/Panel/Category/Create.cshtml.cs create mode 100644 src/Presentation/Server/Pages/Panel/Category/Delete.cshtml create mode 100644 src/Presentation/Server/Pages/Panel/Category/Delete.cshtml.cs create mode 100644 src/Presentation/Server/Pages/Panel/Category/Index.cshtml create mode 100644 src/Presentation/Server/Pages/Panel/Category/Index.cshtml.cs create mode 100644 src/Presentation/Server/Pages/Panel/Category/Update.cshtml create mode 100644 src/Presentation/Server/Pages/Panel/Category/Update.cshtml.cs diff --git a/src/Core/Application/Aggregates/Categorys/CategorysApplication.cs b/src/Core/Application/Aggregates/Categorys/CategorysApplication.cs new file mode 100644 index 0000000..dd79dfc --- /dev/null +++ b/src/Core/Application/Aggregates/Categorys/CategorysApplication.cs @@ -0,0 +1,94 @@ +using Application.Aggregates.Categorys.ViewModels; +using Domain.Aggregates.Categorys; +using Domain.Aggregates.Categorys.Data; +using Mapster; +using Resources.Messages; + +namespace Application.Aggregates.Categorys; + +public class CategorysApplication(ICategoryRepository categoryRepository) +{ + public async Task CreateAsync(CreateCategoryViewModel categoryViewModel) + { + var category = Category.Create( + name: categoryViewModel.Name, + description: categoryViewModel.Description); + + + if (categoryViewModel.IsActive == true) + { + category.Activate(); + } + + await categoryRepository.AddAsync(category); + await categoryRepository.SaveChangesAsync(); + + return category.Adapt(); + } + + public async Task> GetAllAsync() + { + var category = + await categoryRepository.GetAllAsync(); + + return category.Adapt>(); + } + + public async Task GetAsync(Guid categoryId) + { + var category = + await categoryRepository.GetAsync(categoryId); + + return category.Adapt(); + } + + public async Task UpdateAsync(UpdateCategoryViewModel updateCategoryView) + { + var update = + await categoryRepository.GetAsync(updateCategoryView.Id); + + if (update == null || updateCategoryView.Id == Guid.Empty) + { + var error = + string.Format(Errors.NotFound, Resources.DataDictionary.Store); + + throw new Exception(error); + } + + update.Update( + name: updateCategoryView.Name, + description: updateCategoryView.Description); + + + if (updateCategoryView.IsActive == true) + { + update.Activate(); + } + else + { + update.Deactivate(); + } + + await categoryRepository.SaveChangesAsync(); + + return update.Adapt(); + } + + public async Task DeleteAsync(Guid categoryId) + { + var delete = + await categoryRepository.GetAsync(categoryId); + + if (delete == null || delete.Id == Guid.Empty) + { + var error = + string.Format(Errors.NotFound, Resources.DataDictionary.Store); + + throw new Exception(error); + } + + categoryRepository.Remove(delete); + + await categoryRepository.SaveChangesAsync(); + } +} diff --git a/src/Core/Application/Aggregates/Categorys/ViewModels/CategoryViewModel.cs b/src/Core/Application/Aggregates/Categorys/ViewModels/CategoryViewModel.cs new file mode 100644 index 0000000..ebbbf9f --- /dev/null +++ b/src/Core/Application/Aggregates/Categorys/ViewModels/CategoryViewModel.cs @@ -0,0 +1,6 @@ +namespace Application.Aggregates.Categorys.ViewModels; + +public class CategoryViewModel : UpdateCategoryViewModel +{ + +} diff --git a/src/Core/Application/Aggregates/Categorys/ViewModels/CreateCategoryViewModel.cs b/src/Core/Application/Aggregates/Categorys/ViewModels/CreateCategoryViewModel.cs new file mode 100644 index 0000000..574cdf7 --- /dev/null +++ b/src/Core/Application/Aggregates/Categorys/ViewModels/CreateCategoryViewModel.cs @@ -0,0 +1,13 @@ +namespace Application.Aggregates.Categorys.ViewModels; + +public class CreateCategoryViewModel +{ + public CreateCategoryViewModel() + { + + } + + public string Name { get; set; } + public string Description { get; set; } + public bool IsActive { get; set; } +} diff --git a/src/Core/Application/Aggregates/Categorys/ViewModels/UpdateCategoryViewModel.cs b/src/Core/Application/Aggregates/Categorys/ViewModels/UpdateCategoryViewModel.cs new file mode 100644 index 0000000..dc30de0 --- /dev/null +++ b/src/Core/Application/Aggregates/Categorys/ViewModels/UpdateCategoryViewModel.cs @@ -0,0 +1,6 @@ +namespace Application.Aggregates.Categorys.ViewModels; + +public class UpdateCategoryViewModel : CreateCategoryViewModel +{ + public Guid Id { get; set; } +} diff --git a/src/Core/Domain/Aggregates/Categorys/Category.cs b/src/Core/Domain/Aggregates/Categorys/Category.cs new file mode 100644 index 0000000..68863d6 --- /dev/null +++ b/src/Core/Domain/Aggregates/Categorys/Category.cs @@ -0,0 +1,46 @@ +using Domain.Aggregates.Categorys; +using Domain.SeedWork; +using Framework.DataType; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Domain.Aggregates.Categorys +{ + public class Category : Entity + { + public Category() + { + ////********** + } + + private Category(string name,string description) + { + Name = name; + Description = description; + } + + public string Name { get; set; } + public string Description { get; set; } + + public static Category Create(string name,string description) + { + var category = new Category( + name: name.Fix() ?? "", + description: description.Fix() ?? ""); + + return category; + } + + public void Update(string name, string description) + { + Name = name.Fix() ?? ""; + Description = description.Fix() ?? ""; + + + SetUpdateDateTime(); + } + } +} diff --git a/src/Core/Domain/Aggregates/Categorys/Data/ICategoryRepository.cs b/src/Core/Domain/Aggregates/Categorys/Data/ICategoryRepository.cs new file mode 100644 index 0000000..b50327a --- /dev/null +++ b/src/Core/Domain/Aggregates/Categorys/Data/ICategoryRepository.cs @@ -0,0 +1,10 @@ +namespace Domain.Aggregates.Categorys.Data; + +public interface ICategoryRepository +{ + Task AddAsync(Category category); + Task> GetAllAsync(); + Task GetAsync(Guid categoryId); + void Remove(Category category); + Task SaveChangesAsync(); +} diff --git a/src/Persistence/Persistence/DatabaseContext.cs b/src/Persistence/Persistence/DatabaseContext.cs index 072ed50..9c6c87d 100644 --- a/src/Persistence/Persistence/DatabaseContext.cs +++ b/src/Persistence/Persistence/DatabaseContext.cs @@ -2,6 +2,7 @@ using Domain.Aggregates.Users; using Domain.Aggregates.Products; using Microsoft.EntityFrameworkCore; +using Domain.Aggregates.Categorys; namespace Persistence; @@ -16,5 +17,6 @@ public class DatabaseContext: DbContext public DbSet Users { get; set; } public DbSet Stores { get; set; } public DbSet Products { get; set; } + public DbSet Category { get; set; } } diff --git a/src/Persistence/Persistence/Repositories/Aggregates/Categorys/CategoryRepository.cs b/src/Persistence/Persistence/Repositories/Aggregates/Categorys/CategoryRepository.cs new file mode 100644 index 0000000..f7da361 --- /dev/null +++ b/src/Persistence/Persistence/Repositories/Aggregates/Categorys/CategoryRepository.cs @@ -0,0 +1,51 @@ +using Domain.Aggregates.Categorys; +using Domain.Aggregates.Categorys.Data; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace Persistence.Repositories.Aggregates.Categorys; + +public class CategoryRepository(DatabaseContext databaseContext) : ICategoryRepository +{ + public async Task AddAsync(Category categorys) + { + await databaseContext.AddAsync(categorys); + } + + public async Task> GetAllAsync() + { + var category = + await databaseContext.Category + .Where(x => x.IsDeleted == false) + .ToListAsync(); + + return category; + } + + public async Task GetAsync(Guid categoryId) + { + var category = + await databaseContext.Category + .Where(x => x.IsDeleted == false) + .Where(x => x.Id == categoryId) + .FirstOrDefaultAsync(); + + return category; + } + + public void Remove(Category category) + { + category.Delete(); + } + + public async Task SaveChangesAsync() + { + await databaseContext.SaveChangesAsync(); + } +} + diff --git a/src/Presentation/Server/Pages/Index.cshtml b/src/Presentation/Server/Pages/Index.cshtml index 1365887..07ec81e 100644 --- a/src/Presentation/Server/Pages/Index.cshtml +++ b/src/Presentation/Server/Pages/Index.cshtml @@ -9,4 +9,5 @@ [ Users ] [ Stores ] [ Products ] + [ Category ] diff --git a/src/Presentation/Server/Pages/Panel/Category/Create.cshtml b/src/Presentation/Server/Pages/Panel/Category/Create.cshtml new file mode 100644 index 0000000..5781a4c --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Create.cshtml @@ -0,0 +1,37 @@ +@page +@model Server.Pages.Panel.Category.CreateModel +@{ + var pageTitle = + $"{Resources.DataDictionary.CreateOf} {Resources.DataDictionary.Category}"; + + ViewData[Constants.ViewDataKeyName.PageTitle] = pageTitle; +} +
+ + + +
+ + + @(pageTitle) + + + + + + + + + + + +
+ + + + + + +
+ +
\ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Category/Create.cshtml.cs b/src/Presentation/Server/Pages/Panel/Category/Create.cshtml.cs new file mode 100644 index 0000000..5ab184b --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Create.cshtml.cs @@ -0,0 +1,28 @@ +using Application.Aggregates.Categorys; +using Application.Aggregates.Categorys.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Category; + +public class CreateModel(CategorysApplication categorysApplication) : PageModel +{ + [BindProperty] + public CreateCategoryViewModel categoryViewModel { get; set; } + + public void OnGet() + { + } + + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { + return Page(); + } + + await categorysApplication.CreateAsync(categoryViewModel); + + return RedirectToPage("Index"); + } +} diff --git a/src/Presentation/Server/Pages/Panel/Category/Delete.cshtml b/src/Presentation/Server/Pages/Panel/Category/Delete.cshtml new file mode 100644 index 0000000..c46d60f --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Delete.cshtml @@ -0,0 +1,37 @@ +@page +@model Server.Pages.Panel.Category.DeleteModel +@{ + var pageTitle = + $"{Resources.DataDictionary.CreateOf} {Resources.DataDictionary.Category}"; + + ViewData[Constants.ViewDataKeyName.PageTitle] = pageTitle; +} +
+ + + + + +
+ + + @(pageTitle) + + + + + + + + + + +
+ + + + + +
+ +
\ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Category/Delete.cshtml.cs b/src/Presentation/Server/Pages/Panel/Category/Delete.cshtml.cs new file mode 100644 index 0000000..32c56b1 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Delete.cshtml.cs @@ -0,0 +1,37 @@ +using Application.Aggregates.Categorys; +using Application.Aggregates.Categorys.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Category; + +public class DeleteModel(CategorysApplication categorysApplication) : PageModel +{ + [BindProperty] + public CategoryViewModel DeleteViewModel { get; set; } = new(); + + public async Task OnGetAsync(Guid id) + { + if (id == Guid.Empty) + { + return RedirectToPage("Index"); + } + + DeleteViewModel = + await categorysApplication.GetAsync(id); + + if (DeleteViewModel == null) + { + return RedirectToPage("Index"); + } + + return Page(); + } + + public async Task OnPostAsync() + { + await categorysApplication.DeleteAsync(DeleteViewModel.Id); + + return RedirectToPage("Index"); + } +} diff --git a/src/Presentation/Server/Pages/Panel/Category/Index.cshtml b/src/Presentation/Server/Pages/Panel/Category/Index.cshtml new file mode 100644 index 0000000..cd59470 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Index.cshtml @@ -0,0 +1,33 @@ +@page +@model Server.Pages.Panel.Category.IndexModel +@{ +} + + + + + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.Name)) + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.Description)) + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.IsActive)) + + + + + @foreach (var item in Model.category) + { + + @(Html.Ub_DisplayStringWithTd(item.Name)) + @(Html.Ub_DisplayStringWithTd(item.Description)) + @(Html.Ub_DisplayBooleanWithTd(item.IsActive)) + + + } + +
+ +
diff --git a/src/Presentation/Server/Pages/Panel/Category/Index.cshtml.cs b/src/Presentation/Server/Pages/Panel/Category/Index.cshtml.cs new file mode 100644 index 0000000..d6e5ec1 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Index.cshtml.cs @@ -0,0 +1,15 @@ +using Application.Aggregates.Categorys; +using Application.Aggregates.Categorys.ViewModels; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Category; + +public class IndexModel(CategorysApplication categorysApplication) : PageModel +{ + public List category { get; set; } = new(); + + public async Task OnGetAsync() + { + category = await categorysApplication.GetAllAsync(); + } +} \ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Category/Update.cshtml b/src/Presentation/Server/Pages/Panel/Category/Update.cshtml new file mode 100644 index 0000000..e217840 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Update.cshtml @@ -0,0 +1,38 @@ +@page +@model Server.Pages.Panel.Category.UpdateModel +@{ + var pageTitle = + $"{Resources.DataDictionary.CreateOf} {Resources.DataDictionary.Category}"; + + ViewData[Constants.ViewDataKeyName.PageTitle] = pageTitle; +} +
+ + + +
+ + + @(pageTitle) + + + + + + + + + + + + +
+ + + + + + +
+ +
diff --git a/src/Presentation/Server/Pages/Panel/Category/Update.cshtml.cs b/src/Presentation/Server/Pages/Panel/Category/Update.cshtml.cs new file mode 100644 index 0000000..1386f77 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Category/Update.cshtml.cs @@ -0,0 +1,43 @@ +using Application.Aggregates.Categorys; +using Application.Aggregates.Categorys.ViewModels; +using Application.Aggregates.Products; +using Application.Aggregates.Products.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Category; + +public class UpdateModel(CategorysApplication categorysApplication) : PageModel +{ + [BindProperty] + public CategoryViewModel UpdateViewModel { get; set; } + + public async Task OnGetAsync(Guid id) + { + if (id == Guid.Empty) + { + return RedirectToPage("Index"); + } + + UpdateViewModel = + await categorysApplication.GetAsync(id); + + if (UpdateViewModel == null) + { + return RedirectToPage("Index"); + } + + return Page(); + } + + public async Task OnPostAsync() + { + if (ModelState.IsValid) + { + await categorysApplication.UpdateAsync(UpdateViewModel); + } + + return RedirectToPage("Index"); + } +} + diff --git a/src/Presentation/Server/Program.cs b/src/Presentation/Server/Program.cs index fc359f7..e1dbe65 100644 --- a/src/Presentation/Server/Program.cs +++ b/src/Presentation/Server/Program.cs @@ -1,11 +1,14 @@ +using Application.Aggregates.Categorys; using Application.Aggregates.Products; using Application.Aggregates.Stores; using Application.Aggregates.Users; +using Domain.Aggregates.Categorys.Data; using Domain.Aggregates.Products.Data; using Domain.Aggregates.Stores.Data; using Domain.Aggregates.Users.Data; using Microsoft.EntityFrameworkCore; using Persistence; +using Persistence.Repositories.Aggregates.Categorys; using Persistence.Repositories.Aggregates.Products; using Persistence.Repositories.Aggregates.Stores; using Persistence.Repositories.Aggregates.Users; @@ -40,6 +43,9 @@ public class Program builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + var app = builder.Build(); if (!app.Environment.IsDevelopment())