diff --git a/src/Core/Application/Aggregates/Stores/StoresApplication.cs b/src/Core/Application/Aggregates/Stores/StoresApplication.cs new file mode 100644 index 0000000..d039da2 --- /dev/null +++ b/src/Core/Application/Aggregates/Stores/StoresApplication.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Application.Aggregates.Stores.ViewModels; +using Domain.Aggregates.Stores; +using Domain.Aggregates.Stores.Data; +using Mapster; +using Resources.Messages; + +namespace Application.Aggregates.Stores; + +public class StoresApplication(IStoreRepository storeRepository) +{ + public async Task CreateAsync(CreateStoreViewModel storeViewModel) + { + var store = Store.Create( + name: storeViewModel.Name, + address: storeViewModel.Address, + mobile: storeViewModel.Mobile, + score: storeViewModel.Score); + + if (storeViewModel.IsActive == true) + { + store.Activate(); + } + + await storeRepository.AddAsync(store); + await storeRepository.SaveChangesAsync(); + + return store.Adapt(); + } + + public async Task> GetStors() + { + var store = + await storeRepository.GetAllAsync(); + + return store.Adapt>(); + } + + public async Task GetAsync(Guid storeId) + { + var store = + await storeRepository.GetAsync(storeId); + + return store.Adapt(); + } + + public async Task UpdateAsync(UpdateStoreViewModel updateStoreViewModel) + { + var update = + await storeRepository.GetAsync(updateStoreViewModel.Id); + + if (update == null || updateStoreViewModel.Id == Guid.Empty) + { + var error = + string.Format(Errors.NotFound, Resources.DataDictionary.Store); + + throw new Exception(error); + } + + update.Update( + name: updateStoreViewModel.Name, + address: updateStoreViewModel.Address, + mobile: updateStoreViewModel.Mobile, + score: updateStoreViewModel.Score); + + if (update.IsActive == true) + { + update.Activate(); + } + else + { + update.Deactivate(); + } + + await storeRepository.SaveChangesAsync(); + + return update.Adapt(); + } + + public async Task DeleteAsync(Guid storeId) + { + var delete = + await storeRepository.GetAsync(storeId); + + if (delete == null || delete.Id == Guid.Empty) + { + var error = + string.Format(Errors.NotFound, Resources.DataDictionary.Store); + + throw new Exception(error); + } + + storeRepository.Remove(delete); + + await storeRepository.SaveChangesAsync(); + } +} diff --git a/src/Core/Application/Aggregates/Stores/ViewModels/CreateStoreViewModel.cs b/src/Core/Application/Aggregates/Stores/ViewModels/CreateStoreViewModel.cs new file mode 100644 index 0000000..508ce8c --- /dev/null +++ b/src/Core/Application/Aggregates/Stores/ViewModels/CreateStoreViewModel.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Aggregates.Stores.ViewModels; + +public class CreateStoreViewModel +{ + public CreateStoreViewModel() + { + } + + + public string Name { get; set; } + public string Address { get; set; } + public string Mobile { get; set; } + public int Score { get; set; } + public bool IsActive { get; set; } +} diff --git a/src/Core/Application/Aggregates/Stores/ViewModels/StoreViewModel.cs b/src/Core/Application/Aggregates/Stores/ViewModels/StoreViewModel.cs new file mode 100644 index 0000000..29b001a --- /dev/null +++ b/src/Core/Application/Aggregates/Stores/ViewModels/StoreViewModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Aggregates.Stores.ViewModels; + +public class StoreViewModel : UpdateStoreViewModel +{ + public StoreViewModel() + { + } +} diff --git a/src/Core/Application/Aggregates/Stores/ViewModels/UpdateStoreViewModel.cs b/src/Core/Application/Aggregates/Stores/ViewModels/UpdateStoreViewModel.cs new file mode 100644 index 0000000..d2771b7 --- /dev/null +++ b/src/Core/Application/Aggregates/Stores/ViewModels/UpdateStoreViewModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Aggregates.Stores.ViewModels; + +public class UpdateStoreViewModel : CreateStoreViewModel +{ + public UpdateStoreViewModel() + { + } + + public Guid Id { get; set; } +} diff --git a/src/Core/Domain/Aggregates/Stores/Data/IStoreRepository.cs b/src/Core/Domain/Aggregates/Stores/Data/IStoreRepository.cs new file mode 100644 index 0000000..c1c84ea --- /dev/null +++ b/src/Core/Domain/Aggregates/Stores/Data/IStoreRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Domain.Aggregates.Stores.Data; + +public interface IStoreRepository +{ + Task AddAsync(Store store); + Task> GetAllAsync(); + Task GetAsync(Guid storeId); + void Remove(Store store); + Task SaveChangesAsync(); + +} diff --git a/src/Core/Domain/Aggregates/Stores/Store.cs b/src/Core/Domain/Aggregates/Stores/Store.cs new file mode 100644 index 0000000..48a3382 --- /dev/null +++ b/src/Core/Domain/Aggregates/Stores/Store.cs @@ -0,0 +1,69 @@ +using Domain.SeedWork; +using Framework.DataType; +using Resources.Messages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Domain.Aggregates.Stores; + +public class Store : Entity +{ + public Store() + { + ////********** + } + + private Store(string name, string address, string mobile, int score) + { + Name = name; + Address = address; + Mobile = mobile; + Score = score; + } + + + public string Name { get; private set; } + public string Address { get; private set; } + public string Mobile { get; private set; } + public int Score { get; private set; } + + public static Store Create(string name, string address, string mobile, int score) + { + if (!mobile.IsValidMobile()) + { + var error = + string.Format(Errors.Invalid, Resources.DataDictionary.CellPhonenumber); + + throw new InvalidDataException(error); + } + + var store = new Store( + name: name.Fix() ?? "", + address: address.Fix() ?? "", + mobile: mobile, + score: score); + + return store; + } + + public void Update(string name, string address, string mobile, int score) + { + if (!mobile.IsValidMobile()) + { + var error = + string.Format(Errors.Invalid, Resources.DataDictionary.CellPhonenumber); + + throw new InvalidDataException(error); + } + + Name = name.Fix() ?? ""; + Address = address.Fix() ?? ""; + Mobile = mobile; + Score = score; + + SetUpdateDateTime(); + } +} diff --git a/src/Core/Resources/DataDictionary.Designer.cs b/src/Core/Resources/DataDictionary.Designer.cs index 3bcdd68..8ba34b3 100644 --- a/src/Core/Resources/DataDictionary.Designer.cs +++ b/src/Core/Resources/DataDictionary.Designer.cs @@ -1194,6 +1194,15 @@ namespace Resources { } } + /// + /// Looks up a localized string similar to Score. + /// + public static string Score { + get { + return ResourceManager.GetString("Score", resourceCulture); + } + } + /// /// Looks up a localized string similar to Searching. /// diff --git a/src/Core/Resources/DataDictionary.fa-IR.resx b/src/Core/Resources/DataDictionary.fa-IR.resx index cf7e82c..2238e7e 100644 --- a/src/Core/Resources/DataDictionary.fa-IR.resx +++ b/src/Core/Resources/DataDictionary.fa-IR.resx @@ -612,4 +612,7 @@ شماره فاکتور + + امتیاز + \ No newline at end of file diff --git a/src/Core/Resources/DataDictionary.resx b/src/Core/Resources/DataDictionary.resx index d9fac14..cfdd5ae 100644 --- a/src/Core/Resources/DataDictionary.resx +++ b/src/Core/Resources/DataDictionary.resx @@ -612,4 +612,7 @@ Invoicenumber + + Score + \ No newline at end of file diff --git a/src/Persistence/Persistence/DatabaseContext.cs b/src/Persistence/Persistence/DatabaseContext.cs index 7a04f37..31fc3b8 100644 --- a/src/Persistence/Persistence/DatabaseContext.cs +++ b/src/Persistence/Persistence/DatabaseContext.cs @@ -1,4 +1,5 @@ -using Domain.Aggregates.Users; +using Domain.Aggregates.Stores; +using Domain.Aggregates.Users; using Microsoft.EntityFrameworkCore; namespace Persistence; @@ -12,5 +13,6 @@ public class DatabaseContext: DbContext public DbSet Users { get; set; } + public DbSet Stores { get; set; } } diff --git a/src/Persistence/Persistence/Repositories/Aggregates/Stores/StoreRepository.cs b/src/Persistence/Persistence/Repositories/Aggregates/Stores/StoreRepository.cs new file mode 100644 index 0000000..5f85ca5 --- /dev/null +++ b/src/Persistence/Persistence/Repositories/Aggregates/Stores/StoreRepository.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Domain.Aggregates.Stores; +using Domain.Aggregates.Stores.Data; +using Microsoft.EntityFrameworkCore; + +namespace Persistence.Repositories.Aggregates.Stores; + +public class StoreRepository(DatabaseContext databaseContext) : IStoreRepository +{ + public async Task AddAsync(Store store) + { + await databaseContext.AddAsync(store); + } + + public async Task> GetAllAsync() + { + var store = + await databaseContext.Stores + .Where(x => x.IsDeleted == false) + .ToListAsync(); + + return store; + } + + public async Task GetAsync(Guid storeId) + { + var store = + await databaseContext.Stores + .Where(x => x.IsDeleted == false) + .Where(x => x.Id == storeId) + .FirstOrDefaultAsync(); + + return store; + } + + public void Remove(Store store) + { + store.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 7ff81b5..5042f38 100644 --- a/src/Presentation/Server/Pages/Index.cshtml +++ b/src/Presentation/Server/Pages/Index.cshtml @@ -7,4 +7,5 @@ diff --git a/src/Presentation/Server/Pages/Panel/Stores/Create.cshtml b/src/Presentation/Server/Pages/Panel/Stores/Create.cshtml new file mode 100644 index 0000000..7288dbc --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Create.cshtml @@ -0,0 +1,42 @@ +@page +@model Server.Pages.Panel.Stores.CreateModel +@{ + var pageTitle = + $"{Resources.DataDictionary.CreateOf} {Resources.DataDictionary.Store}"; + + ViewData[Constants.ViewDataKeyName.PageTitle] = pageTitle; +} + +
+ + + +
+ + + @(pageTitle) + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
\ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Stores/Create.cshtml.cs b/src/Presentation/Server/Pages/Panel/Stores/Create.cshtml.cs new file mode 100644 index 0000000..9bb467d --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Create.cshtml.cs @@ -0,0 +1,29 @@ +using Application.Aggregates.Stores; +using Application.Aggregates.Stores.ViewModels; +using Application.Aggregates.Users.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Stores; + +public class CreateModel(StoresApplication storesApplication) : PageModel +{ + [BindProperty] + public CreateStoreViewModel CreateViewModel { get; set; } = new(); + + public void OnGet() + { + } + + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { + return Page(); + } + + await storesApplication.CreateAsync(CreateViewModel); + + return RedirectToPage("Index"); + } +} diff --git a/src/Presentation/Server/Pages/Panel/Stores/Delete.cshtml b/src/Presentation/Server/Pages/Panel/Stores/Delete.cshtml new file mode 100644 index 0000000..5e5776a --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Delete.cshtml @@ -0,0 +1,43 @@ +@page +@model Server.Pages.Panel.Stores.DeleteModel +@{ + var pageTitle = + $"{Resources.DataDictionary.DeleteOf} {Resources.DataDictionary.Store}"; + + ViewData[Constants.ViewDataKeyName.PageTitle] = pageTitle; +} + + +
+ + + + + +
+ + + @(pageTitle) + + + + + + + + + + + + + + +
+ + + + + +
+ +
\ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Stores/Delete.cshtml.cs b/src/Presentation/Server/Pages/Panel/Stores/Delete.cshtml.cs new file mode 100644 index 0000000..c4e5848 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Delete.cshtml.cs @@ -0,0 +1,38 @@ +using Application.Aggregates.Stores; +using Application.Aggregates.Stores.ViewModels; +using Application.Aggregates.Users; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Stores; + +public class DeleteModel(StoresApplication storesApplication) : PageModel +{ + [BindProperty] + public StoreViewModel DeleteViewModel { get; set; } = new(); + + public async Task OnGetAsync(Guid id) + { + if (id == Guid.Empty) + { + return RedirectToPage("Index"); + } + + DeleteViewModel = + await storesApplication.GetAsync(id); + + if (DeleteViewModel == null) + { + return RedirectToPage("Index"); + } + + return Page(); + } + + public async Task OnPostAsync() + { + await storesApplication.DeleteAsync(DeleteViewModel.Id); + + return RedirectToPage("Index"); + } +} diff --git a/src/Presentation/Server/Pages/Panel/Stores/Index.cshtml b/src/Presentation/Server/Pages/Panel/Stores/Index.cshtml new file mode 100644 index 0000000..f19a662 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Index.cshtml @@ -0,0 +1,38 @@ +@page +@model Server.Pages.Panel.Stores.IndexModel +@{ +} + + + + + + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.Name)) + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.Address)) + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.Mobile)) + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.Score)) + @(Html.Ub_DisplayStringWithTh(Resources.DataDictionary.IsActive)) + + + + + @foreach (var item in Model.store) + { + + @(Html.Ub_DisplayStringWithTd(item.Name)) + @(Html.Ub_DisplayStringWithTd(item.Address)) + @(Html.Ub_DisplayStringWithTd(item.Mobile)) + @(Html.Ub_DisplayInteger(item.Score)) + @(Html.Ub_DisplayBooleanWithTd(item.IsActive)) + + + } + +
+ +
\ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Stores/Index.cshtml.cs b/src/Presentation/Server/Pages/Panel/Stores/Index.cshtml.cs new file mode 100644 index 0000000..6dd8bc3 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Index.cshtml.cs @@ -0,0 +1,16 @@ +using Application.Aggregates.Stores; +using Application.Aggregates.Stores.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Stores; + +public class IndexModel(StoresApplication storesApplication) : PageModel +{ + public List store { get; set; } = new(); + + public async Task OnGetAsync() + { + store = await storesApplication.GetStors(); + } +} diff --git a/src/Presentation/Server/Pages/Panel/Stores/Update.cshtml b/src/Presentation/Server/Pages/Panel/Stores/Update.cshtml new file mode 100644 index 0000000..f9f80de --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Update.cshtml @@ -0,0 +1,43 @@ +@page +@model Server.Pages.Panel.Stores.UpdateModel +@{ + var pageTitle = + $"{Resources.DataDictionary.UpdateOf} {Resources.DataDictionary.Store}"; + + ViewData[Constants.ViewDataKeyName.PageTitle] = pageTitle; +} + +
+ + + +
+ + + @(pageTitle) + + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
\ No newline at end of file diff --git a/src/Presentation/Server/Pages/Panel/Stores/Update.cshtml.cs b/src/Presentation/Server/Pages/Panel/Stores/Update.cshtml.cs new file mode 100644 index 0000000..8134a39 --- /dev/null +++ b/src/Presentation/Server/Pages/Panel/Stores/Update.cshtml.cs @@ -0,0 +1,40 @@ +using Application.Aggregates.Stores; +using Application.Aggregates.Stores.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Server.Pages.Panel.Stores; + +public class UpdateModel(StoresApplication storesApplication) : PageModel +{ + [BindProperty] + public StoreViewModel UpdateViewModel { get; set; } + + public async Task OnGetAsync(Guid id) + { + if(id==Guid.Empty) + { + return RedirectToPage("Index"); + } + + UpdateViewModel= + await storesApplication.GetAsync(id); + + if(UpdateViewModel==null) + { + return RedirectToPage("Index"); + } + + return Page(); + } + + public async Task OnPostAsync() + { + if(ModelState.IsValid) + { + await storesApplication.UpdateAsync(UpdateViewModel); + } + + return RedirectToPage("Index"); + } +} diff --git a/src/Presentation/Server/Program.cs b/src/Presentation/Server/Program.cs index 249def6..059aa92 100644 --- a/src/Presentation/Server/Program.cs +++ b/src/Presentation/Server/Program.cs @@ -1,7 +1,10 @@ +using Application.Aggregates.Stores; using Application.Aggregates.Users; +using Domain.Aggregates.Stores.Data; using Domain.Aggregates.Users.Data; using Microsoft.EntityFrameworkCore; using Persistence; +using Persistence.Repositories.Aggregates.Stores; using Persistence.Repositories.Aggregates.Users; using Server.Infrastructure.Extensions.ServiceCollections; @@ -28,6 +31,9 @@ public class Program builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + var app = builder.Build(); if (!app.Environment.IsDevelopment())