Compare commits

..

No commits in common. "master" and "release" have entirely different histories.

310 changed files with 3930 additions and 29005 deletions

View File

@ -1 +1 @@
1.10.21.36 1.0.3.3

View File

@ -1,8 +1,8 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"PostgresServer": "Host=185.220.227.29;Username=vesmmehAgent;Password=g05CTjK358Vx3Eoc9satsWyVwo+15UmsA2dnCrZRUYh1pLTe;Database=NetinaShopDB;Application Name=NetinaShopApi", "PostgresServer": "Host=185.220.227.107;Username=vesmmehAgent;Password=g05CTjK358Vx3Eoc9satsWyVwo+15UmsA2dnCrZRUYh1pLTe;Database=NetinaShopDB;Application Name=NetinaShopApi",
"Postgres": "Host=pg-0;Username=postgres;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=NetinaShopDB", "Postgres": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=NetinaShopDB;Load Balance Hosts=true;Target Session Attributes=primary;Application Name=iGLS",
"MartenDB": "Host=pg-0;Username=postgres;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=NetinaShopMartenDB" "MartenDB": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=NetinaShopMartenDB;"
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {

View File

@ -11,7 +11,7 @@ public class BlogCategoryController : ICarterModule
.MapGroup($"api/blog/category"); .MapGroup($"api/blog/category");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get BlogCategories") .WithDisplayName("GetAllCategories")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
@ -20,17 +20,14 @@ public class BlogCategoryController : ICarterModule
group.MapPost("", Post) group.MapPost("", Post)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission,ApplicationPermission.ManageBlogs)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission,ApplicationPermission.ManageBlogs))
.WithDisplayName("Create BlogCategory")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Update BlogCategory")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Delete BlogCategory")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -1,7 +1,8 @@
using Microsoft.Extensions.Options; using Marten.Events;
using Microsoft.Extensions.Options;
using Netina.Domain.Entities.Blogs; using Netina.Domain.Entities.Blogs;
using Netina.Domain.Entities.Products;
using System.Web; using System.Web;
using Netina.Repository.Abstracts;
namespace Netina.Api.Controllers; namespace Netina.Api.Controllers;
@ -14,7 +15,7 @@ public class BlogController : ICarterModule
.MapGroup($"api/blog"); .MapGroup($"api/blog");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Blogs") .WithDisplayName("GetAllBlogs")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
@ -25,25 +26,18 @@ public class BlogController : ICarterModule
.RequireAuthorization(builder => .RequireAuthorization(builder =>
builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser() builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()
.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Create Blog")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.RequireAuthorization(builder => .RequireAuthorization(builder =>
builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser() builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()
.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Update Blog")
.HasApiVersion(1.0);
group.MapGet("{blogId}/comment", GetBlogCommentsAsync)
.WithDisplayName("Get Blog Comments")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.RequireAuthorization(builder => .RequireAuthorization(builder =>
builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser() builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()
.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Delete Blog")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("/newlink", GetBlogNewLinkAsync) group.MapGet("/newlink", GetBlogNewLinkAsync)
@ -52,10 +46,6 @@ public class BlogController : ICarterModule
} }
private async Task<IResult> GetBlogCommentsAsync([FromQuery] int page, [FromQuery] int count, [FromRoute] Guid blogId, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetCommentsQuery(page, count, null, blogId), cancellationToken));
private async Task<IResult> GetBlogNewLinkAsync([FromQuery]string slug,IRepositoryWrapper repositoryWrapper,IOptionsSnapshot<SiteSettings> snapshot,CancellationToken cancellationToken) private async Task<IResult> GetBlogNewLinkAsync([FromQuery]string slug,IRepositoryWrapper repositoryWrapper,IOptionsSnapshot<SiteSettings> snapshot,CancellationToken cancellationToken)
{ {
var htmlSlug = HttpUtility.UrlEncode(slug); var htmlSlug = HttpUtility.UrlEncode(slug);
@ -86,19 +76,13 @@ public class BlogController : ICarterModule
} }
// POST:Create Entity // POST:Create Entity
public async Task<IResult> Post([FromBody] BlogLDto dto, IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService, CancellationToken cancellationToken) public async Task<IResult> Post([FromBody] BlogLDto dto, IRepositoryWrapper repositoryWrapper, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) var ent = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested,dto.CategoryId);
throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong");
if (!Guid.TryParse(currentUserService.UserId, out Guid userId))
throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong");
var ent = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested,dto.CategoryId, userId);
foreach (var file in dto.Files) foreach (var file in dto.Files)
{ {
ent.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType); ent.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType);
} }
foreach (var item in dto.MetaTags)
ent.AddMetaTag(item.Type, item.Value);
repositoryWrapper.SetRepository<Blog>().Add(ent); repositoryWrapper.SetRepository<Blog>().Add(ent);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await repositoryWrapper.SaveChangesAsync(cancellationToken);
@ -106,17 +90,13 @@ public class BlogController : ICarterModule
} }
// PUT:Update Entity // PUT:Update Entity
public async Task<IResult> Put([FromBody] BlogLDto dto, IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService, CancellationToken cancellationToken) public async Task<IResult> Put([FromBody] BlogLDto dto, IRepositoryWrapper repositoryWrapper, CancellationToken cancellationToken)
{ {
var ent = await repositoryWrapper.SetRepository<Blog>().TableNoTracking var ent = await repositoryWrapper.SetRepository<Blog>().TableNoTracking
.FirstOrDefaultAsync(b => b.Id == dto.Id, cancellationToken); .FirstOrDefaultAsync(b => b.Id == dto.Id, cancellationToken);
if (ent == null) if (ent == null)
throw new AppException("Blog not found"); throw new AppException("Blog not found");
if (currentUserService.UserId == null) var newEnt = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested, dto.CategoryId);
throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong");
if (!Guid.TryParse(currentUserService.UserId, out Guid userId))
throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong");
var newEnt = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested, dto.CategoryId, userId);
newEnt.Id = ent.Id; newEnt.Id = ent.Id;
newEnt.CreatedAt = ent.CreatedAt; newEnt.CreatedAt = ent.CreatedAt;
newEnt.CreatedBy = ent.CreatedBy; newEnt.CreatedBy = ent.CreatedBy;
@ -134,21 +114,6 @@ public class BlogController : ICarterModule
foreach (var file in dto.Files.Where(f => f.Id == default)) foreach (var file in dto.Files.Where(f => f.Id == default))
newEnt.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType); newEnt.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType);
//Check MetaTags
var dbMetaTags = await repositoryWrapper.SetRepository<BlogMetaTag>()
.TableNoTracking
.Where(f => f.BlogId == ent.Id)
.ToListAsync(cancellationToken);
foreach (var feature in dbMetaTags.Where(feature => dto.MetaTags.Any(f => f.Type == feature.Type) == false))
{
repositoryWrapper.SetRepository<BlogMetaTag>()
.Delete(feature);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
}
foreach (var item in dto.MetaTags.Where(f => dbMetaTags.Any(dbf => dbf.Type == f.Type) == false))
newEnt.AddMetaTag(item.Type, item.Value);
repositoryWrapper.SetRepository<Blog>().Update(newEnt); repositoryWrapper.SetRepository<Blog>().Update(newEnt);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await repositoryWrapper.SaveChangesAsync(cancellationToken);
return TypedResults.Ok(); return TypedResults.Ok();

View File

@ -11,26 +11,23 @@ public class BrandController : ICarterModule
.MapGroup($"api/brand"); .MapGroup($"api/brand");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Brands") .WithDisplayName("GetAllBrands")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Brand") .WithDisplayName("GetBlogBrand")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", Post) group.MapPost("", Post)
.HasApiVersion(1.0) .HasApiVersion(1.0)
.WithDisplayName("Create Brand")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBrands)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBrands));
group.MapPut("", Put) group.MapPut("", Put)
.HasApiVersion(1.0) .HasApiVersion(1.0)
.WithDisplayName("Update Brand")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBrands)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBrands));
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.HasApiVersion(1.0) .HasApiVersion(1.0)
.WithDisplayName("Delete Brand")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBrands)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBrands));
} }

View File

@ -1,17 +0,0 @@
namespace Netina.Api.Controllers;
public class CustomerController : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Customer").MapGroup("api/customer")
.RequireAuthorization(builder=>builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetCustomersAsync)
.WithDisplayName("Get Customers")
.HasApiVersion(1.0);
}
private async Task<IResult> GetCustomersAsync([FromQuery] int page, [FromQuery] int? count, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(true);
}

View File

@ -15,6 +15,8 @@ public class DashboardController : ICarterModule
group.MapGet("orders", GetOrdersDashboardAsync) group.MapGet("orders", GetOrdersDashboardAsync)
.WithDisplayName("Get Orders Dashboard") .WithDisplayName("Get Orders Dashboard")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }
private async Task<IResult> GetOrdersDashboardAsync([FromServices] IDashboardService dashboardService, CancellationToken cancellationToken) private async Task<IResult> GetOrdersDashboardAsync([FromServices] IDashboardService dashboardService, CancellationToken cancellationToken)

View File

@ -9,7 +9,7 @@ public class DiscountController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Discounts") .WithDisplayName("GetAllDiscounts")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts, ApplicationPermission.ViewDiscounts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts, ApplicationPermission.ViewDiscounts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -20,17 +20,14 @@ public class DiscountController : ICarterModule
group.MapPost("", Post) group.MapPost("", Post)
.HasApiVersion(1.0) .HasApiVersion(1.0)
.WithDisplayName("Create Discount")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts));
group.MapPut("", Put) group.MapPut("", Put)
.HasApiVersion(1.0) .HasApiVersion(1.0)
.WithDisplayName("Update Discount")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts));
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.HasApiVersion(1.0) .HasApiVersion(1.0)
.WithDisplayName("Delete Discount")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageDiscounts));
} }

View File

@ -11,7 +11,7 @@ public class DistrictController : ICarterModule
.WithDisplayName("Get Cities") .WithDisplayName("Get Cities")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("province", GetProvincesAsync) group.MapGet("province", GetProvincesAsync)
.WithDisplayName("Get Provinces") .WithDisplayName("Get Cities")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -1,56 +0,0 @@
namespace Netina.Api.Controllers;
public class FaqController : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Faq")
.MapGroup("api/faq");
group.MapGet("/slug", GetFaqBySlugAsync)
.WithDisplayName("Get Faq By Slug")
.WithDescription("Get faq by slug , you have to send page slug")
.HasApiVersion(1.0);
group.MapGet("", GetFaqsAsync)
.WithDisplayName("Get Faqs")
.WithDescription("Get All Faqs")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer")
.RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageFaq))
.HasApiVersion(1.0);
group.MapPost("", CreateFaqAsync)
.WithDisplayName("Create Faq")
.WithDescription("Create Faq , you can create new faq or create update your faq ")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer")
.RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageFaq))
.HasApiVersion(1.0);
group.MapPut("", UpdateFaqAsync)
.WithDisplayName("Update Faq")
.WithDescription("Update Faq , you can create new faq or create update your faq ")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer")
.RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageFaq))
.HasApiVersion(1.0);
group.MapDelete("{id}", DeleteFaqAsync)
.WithDisplayName("Delete Faq")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageFaq))
.HasApiVersion(1.0);
}
private async Task<IResult> DeleteFaqAsync([FromRoute]Guid id,[FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new DeleteFaqCommand(Id:id), cancellationToken));
private async Task<IResult> GetFaqsAsync([FromQuery]int page, [FromQuery] int? count ,[FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetFaqsQuery(Count: count ?? 0 , Page:page), cancellationToken));
private async Task<IResult> CreateFaqAsync([FromBody] CreateFaqCommand request,[FromServices]IMediator mediator , CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request, cancellationToken));
private async Task<IResult> UpdateFaqAsync([FromBody] UpdateFaqCommand request, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request, cancellationToken));
private async Task<IResult> GetFaqBySlugAsync([FromQuery] string slug, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetFaqQuery(null, slug), cancellationToken));
}

View File

@ -1,5 +1,4 @@
using Netina.Domain.Dtos.ResponseDtos; using Netina.Domain.Enums;
using Netina.Domain.Enums;
namespace Netina.Api.Controllers; namespace Netina.Api.Controllers;
@ -11,57 +10,14 @@ public class FileController : ICarterModule
.MapGroup("api/file"); .MapGroup("api/file");
group.MapGet("", GetFilesAsync) group.MapGet("", GetFilesAsync)
.WithDisplayName("Get Files") .WithDisplayName("GetFilesAsync")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageFiles, ApplicationPermission.ViewFiles)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageFiles, ApplicationPermission.ViewFiles))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", UploadFileAsync) group.MapPost("", UploadFileAsync)
.WithDisplayName("Upload File") .WithDisplayName("UploadFileAsync")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("/ckeditor", UploadCkEditorFileAsync)
.WithDisplayName("Upload CkEditor File")
.AllowAnonymous()
.DisableAntiforgery()
.HasApiVersion(1.0);
}
public async Task<IResult> UploadCkEditorFileAsync(IFormFile upload, [FromServices] IHttpContextAccessor httpContextAccessor, [FromServices] IStorageService storageService, IUploadFileService uploadFileService, CancellationToken cancellationToken)
{
try
{
if (httpContextAccessor.HttpContext?.Request?.Headers is { } dictionary && dictionary.TryGetValue("Authorization", out StringValues value))
{
if (value.ToString() != "xuwp4KzU1/YBoevpzgH0cz8+zLKQ+EOaYXeo4JtRxmVIuN7Hqxz97oQ398tNX68+")
throw new Exception("ارسال فایل از طرف شما معتبر نمی باشد");
using var stream = new MemoryStream();
await upload.CopyToAsync(stream, cancellationToken);
var uploadRequest = new FileUploadRequest
{
FileName = upload.FileName,
ContentType = upload.ContentType,
FileUploadType = FileUploadType.Image,
StringBaseFile = Convert.ToBase64String(stream.ToArray())
};
var fileUrl = await uploadFileService.UploadImageAsync(uploadRequest);
return TypedResults.Ok(new CkEditorFileUploadResponseDto { url = fileUrl.FileUrl });
}
throw new Exception("ارسال فایل از طرف شما معتبر نمی باشد");
}
catch (Exception e)
{
var errorMessage = new
{
message = e.Message
};
var errorResponse = new
{
error = errorMessage
};
return TypedResults.BadRequest(errorResponse);
}
} }
public async Task<IResult> GetFilesAsync([FromQuery]StorageFileType? fileType,[FromServices] IStorageService storageService, CancellationToken cancellationToken) public async Task<IResult> GetFilesAsync([FromQuery]StorageFileType? fileType,[FromServices] IStorageService storageService, CancellationToken cancellationToken)

View File

@ -15,7 +15,7 @@ public class HealthController : ICarterModule
public async Task<IResult> GetHealth([FromServices]ISiteMapService siteMapService) public async Task<IResult> GetHealth([FromServices]ISiteMapService siteMapService)
{ {
await siteMapService.CreateSiteMapAsync(); //await siteMapService.CreateSiteMapAsync();
var version = typeof(Program)?.Assembly.GetName()?.Version?.ToString(); var version = typeof(Program)?.Assembly.GetName()?.Version?.ToString();
var check = new HealthCheck var check = new HealthCheck
{ {

View File

@ -11,12 +11,12 @@ public class MarketerController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetMarketersAsync) group.MapGet("", GetMarketersAsync)
.WithDisplayName("Get Marketers") .WithDisplayName("GetAllMarketers")
.RequireAuthorization(builder=>builder.RequireClaim(CustomClaimType.Permission,ApplicationPermission.ManageUsers , ApplicationPermission.ViewUsers)) .RequireAuthorization(builder=>builder.RequireClaim(CustomClaimType.Permission,ApplicationPermission.ManageUsers , ApplicationPermission.ViewUsers))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("profile", GetMarketerProfileAsync) group.MapGet("profile", GetMarketerProfileAsync)
.WithDisplayName("Get Marketer Profile") .WithDisplayName("GetAllMarketers")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("signup", SignUpMarketerAsync) group.MapPost("signup", SignUpMarketerAsync)
@ -24,7 +24,7 @@ public class MarketerController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("signup/contract", GetSignUpMarketerContractAsync) group.MapGet("signup/contract", GetSignUpMarketerContractAsync)
.WithDisplayName("Get Marketer Contract") .WithDisplayName("SignUpMarketerContract")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -7,7 +7,7 @@ public class NewsletterMemberController : ICarterModule
var group = app.NewVersionedApi("Newsletter Members").MapGroup("api/newsletter/member"); var group = app.NewVersionedApi("Newsletter Members").MapGroup("api/newsletter/member");
group.MapGet("", GetAllMembersAsync) group.MapGet("", GetAllMembersAsync)
.WithDisplayName("Get Members") .WithDisplayName("Get All Members")
.HasApiVersion(1.0) .HasApiVersion(1.0)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewNewsletterMembers)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewNewsletterMembers));

View File

@ -20,7 +20,7 @@ public class OrderBagController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("add", AddProductToBagAsync) group.MapPost("add", AddProductToBagAsync)
.WithDisplayName("Add Product To OrderBag") .WithDisplayName("AddProductToBag")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("remove", RemoveFromOrderBagAsync) group.MapDelete("remove", RemoveFromOrderBagAsync)
@ -32,7 +32,7 @@ public class OrderBagController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("discount/{orderId}", DiscountActionOrderBagAsync) group.MapPost("discount/{orderId}", AddDiscountToOrderBagAsync)
.WithDisplayName("AddDiscountToOrderBag") .WithDisplayName("AddDiscountToOrderBag")
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -62,8 +62,8 @@ public class OrderBagController : ICarterModule
public async Task<IResult> RemoveFromOrderBagAsync([FromBody] List<OrderBagRequestDto> requestDtos, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> RemoveFromOrderBagAsync([FromBody] List<OrderBagRequestDto> requestDtos, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new RemoveFromOrderBagCommand(requestDtos), cancellationToken)); => TypedResults.Ok(await mediator.Send(new RemoveFromOrderBagCommand(requestDtos), cancellationToken));
public async Task<IResult> DiscountActionOrderBagAsync(Guid orderId, [FromQuery] string? discountCode, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> AddDiscountToOrderBagAsync(Guid orderId, [FromQuery] string discountCode, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new SubmitDiscountActionCommand(orderId, discountCode), cancellationToken)); => TypedResults.Ok(await mediator.Send(new SubmitDiscountCommand(orderId, discountCode), cancellationToken));
public async Task<IResult> AddShippingToOrderBagAsync(Guid orderId, [FromBody] SubmitOrderDeliveryCommand request, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> AddShippingToOrderBagAsync(Guid orderId, [FromBody] SubmitOrderDeliveryCommand request, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request with { OrderId = orderId }, cancellationToken)); => TypedResults.Ok(await mediator.Send(request with { OrderId = orderId }, cancellationToken));

View File

@ -10,16 +10,13 @@ public class OrderController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Orders") .WithDisplayName("GetAllOrders")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllOrders , ApplicationPermission.ManageOrders)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllOrders , ApplicationPermission.ManageOrders))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Order") .WithDisplayName("GetOneOrder")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllOrders, ApplicationPermission.ManageOrders))
ApplicationPermission.ViewAllOrders,
ApplicationPermission.ManageOrders,
ApplicationPermission.ViewMineOrders))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("{id}/confirm", ConfirmOrderStepAsync) group.MapPost("{id}/confirm", ConfirmOrderStepAsync)
@ -27,13 +24,8 @@ public class OrderController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageOrders)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageOrders))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("{id}/cancel", CancelOrderStepAsync)
.WithDisplayName("Cancel Order")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageOrders))
.HasApiVersion(1.0);
group.MapDelete("{id}", DeleteAsync) group.MapDelete("{id}", DeleteAsync)
.WithDisplayName("Delete Order") .WithDisplayName("DeleteOneOrder")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageOrders)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageOrders))
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -48,18 +40,8 @@ public class OrderController : ICarterModule
private async Task<IResult> ConfirmOrderStepAsync(Guid id, [FromQuery] OrderStatus nextOrderStatus, [FromQuery]string? trackingCode, [FromServices] IMediator mediator, CancellationToken cancellationToken) private async Task<IResult> ConfirmOrderStepAsync(Guid id, [FromQuery] OrderStatus nextOrderStatus, [FromQuery]string? trackingCode, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new ConfirmOrderStepCommand(id, nextOrderStatus,TrackingCode:trackingCode), cancellationToken)); => TypedResults.Ok(await mediator.Send(new ConfirmOrderStepCommand(id, nextOrderStatus,TrackingCode:trackingCode), cancellationToken));
private async Task<IResult> CancelOrderStepAsync(Guid id, [FromServices] IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> GetAllAsync(IMediator mediator, [FromQuery]string? factorCode, [FromQuery]long? selectedDate, [FromQuery] OrderStatus? orderStatus, [FromQuery] OrderQueryDateFilter? dateFilter, [FromQuery] int page = 0, CancellationToken cancellationToken = default)
=> TypedResults.Ok(await mediator.Send(new CancelOrderStepCommand(id), cancellationToken)); => TypedResults.Ok(await mediator.Send(new GetOrdersQuery(Page:page, FactorCode:factorCode , SelectedDate: selectedDate, OrderStatus:orderStatus, DateFilter:dateFilter), cancellationToken));
public async Task<IResult> GetAllAsync(IMediator mediator,
[FromQuery]string? factorCode,
[FromQuery]long? selectedDate,
[FromQuery]OrderStatus? orderStatus,
[FromQuery]OrderQueryDateFilter? dateFilter,
[FromQuery]bool? orderBags,
[FromQuery]int page = 0,
CancellationToken cancellationToken = default)
=> TypedResults.Ok(await mediator.Send(new GetOrdersQuery(Page:page, FactorCode:factorCode ,OrderBags:orderBags??false , SelectedDate: selectedDate, OrderStatus:orderStatus, DateFilter:dateFilter), cancellationToken));
public async Task<IResult> GetAsync(IMediator mediator, Guid id, CancellationToken cancellationToken = default) public async Task<IResult> GetAsync(IMediator mediator, Guid id, CancellationToken cancellationToken = default)
{ {

View File

@ -12,13 +12,6 @@ public class PageController : ICarterModule
.HasApiVersion(1.0) .HasApiVersion(1.0)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewPages, ApplicationPermission.ManagePages)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewPages, ApplicationPermission.ManagePages));
group.MapGet("redirect/check", CheckRedirectedOldLinkAsync)
.WithDisplayName("Check Redirect OldLink")
.HasApiVersion(1.0);
group.MapGet("deleted/check", CheckDeletedLinkAsync)
.WithDisplayName("Check Deleted Link")
.HasApiVersion(1.0);
group.MapGet("{id}", GetPageByIdAsync) group.MapGet("{id}", GetPageByIdAsync)
.WithDisplayName("Get Page") .WithDisplayName("Get Page")
@ -38,10 +31,6 @@ public class PageController : ICarterModule
.HasApiVersion(1.0) .HasApiVersion(1.0)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManagePages)); .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManagePages));
group.MapPut("", UpdatePageAsync)
.WithDisplayName("Update Page")
.HasApiVersion(1.0)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManagePages));
group.MapDelete("{id}", DeletePageByIdAsync) group.MapDelete("{id}", DeletePageByIdAsync)
.WithDisplayName("Delete Page") .WithDisplayName("Delete Page")
@ -50,35 +39,31 @@ public class PageController : ICarterModule
} }
private async Task<IResult> CheckDeletedLinkAsync([FromQuery] string link, [FromServices] IPageService pageService, CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.CheckDeletedAsync(link, cancellationToken));
private async Task<IResult> CheckRedirectedOldLinkAsync([FromQuery] string oldUrl, [FromServices] IPageService pageService, CancellationToken cancellationToken)
=> TypedResults.Content(await pageService.CheckRedirectAsync(oldUrl, cancellationToken));
private async Task<IResult> DeletePageByIdAsync([FromRoute]Guid id,[FromServices]IPageService pageService,CancellationToken cancellationToken) private async Task<IResult> DeletePageByIdAsync([FromRoute]Guid id,[FromServices]IPageService pageService,CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.DeletePageAsync(id, cancellationToken)); => TypedResults.Ok(await pageService.DeletePageAsync(id, cancellationToken));
public async Task<IResult> GetPagesAsync([FromServices] IPageService pageService, CancellationToken cancellationToken) public async Task<IResult> GetPagesAsync([FromServices] IPageService pageService, CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.GetPagesAsync(cancellationToken)); {
return TypedResults.Ok(await pageService.GetPagesAsync(cancellationToken));
}
public async Task<IResult> GetPageByIdAsync(Guid id ,[FromServices] IPageService pageService, CancellationToken cancellationToken) public async Task<IResult> GetPageByIdAsync(Guid id ,[FromServices] IPageService pageService, CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.GetPageAsync(id: id, cancellationToken: cancellationToken)); {
return TypedResults.Ok(await pageService.GetPageAsync(id: id,cancellationToken: cancellationToken));
}
public async Task<IResult> GetPageByTypeAsync(string type, [FromServices] IPageService pageService, CancellationToken cancellationToken) public async Task<IResult> GetPageByTypeAsync(string type, [FromServices] IPageService pageService, CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.GetPageAsync(type: type, cancellationToken: cancellationToken)); {
return TypedResults.Ok(await pageService.GetPageAsync(type: type, cancellationToken: cancellationToken));
}
public async Task<IResult> GetPageAsync(string pageSlug, [FromServices] IPageService pageService, CancellationToken cancellationToken) public async Task<IResult> GetPageAsync(string pageSlug, [FromServices] IPageService pageService, CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.GetPageAsync(pageSlug: pageSlug, cancellationToken: cancellationToken)); {
return TypedResults.Ok(await pageService.GetPageAsync(pageSlug: pageSlug,cancellationToken: cancellationToken));
}
public async Task<IResult> PostPageAsync([FromBody] PageActionRequestDto page, [FromServices] IPageService pageService, CancellationToken cancellationToken) public async Task<IResult> PostPageAsync([FromBody] PageActionRequestDto page, [FromServices] IPageService pageService, CancellationToken cancellationToken)
{ {
await pageService.CreatePageAsync(page, cancellationToken); await pageService.CreatePageAsync(page, cancellationToken);
return TypedResults.Ok(); return TypedResults.Ok();
} }
public async Task<IResult> UpdatePageAsync([FromBody] PageActionRequestDto page, [FromServices] IPageService pageService, CancellationToken cancellationToken)
{
await pageService.UpdatePageAsync(page, cancellationToken);
return TypedResults.Ok();
}
} }

View File

@ -22,7 +22,6 @@ public class PaymentController : ICarterModule
// .HasApiVersion(1.0); // .HasApiVersion(1.0);
group.MapGet("verify", VerifyPaymentAsync) group.MapGet("verify", VerifyPaymentAsync)
.WithDisplayName("Verify Payment")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -9,25 +9,22 @@ public class ProductCategoryController : ICarterModule
.MapGroup($"api/product/category"); .MapGroup($"api/product/category");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get ProductCategories") .WithDisplayName("GetAllCategories")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
.WithDisplayName("Get ProductCategory") .WithDisplayName("GetCategory")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", Post) group.MapPost("", Post)
.WithDisplayName("Create ProductCategory")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission,ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission,ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.WithDisplayName("Update ProductCategory")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.WithDisplayName("Delete ProductCategory")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -11,61 +11,32 @@ public class ProductController : ICarterModule
.MapGroup($"api/product"); .MapGroup($"api/product");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Products") .WithDisplayName("GetAllProducts")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Product") .WithDisplayName("GetProducts")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", Post) group.MapPost("", Post)
.WithDisplayName("Create Product")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.WithDisplayName("Update Product")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{productId}/sub", GetSubProductsAsync) group.MapPut("{productId}", ChangeDisplayedAsync)
.WithDisplayName("Get Sub Products")
.HasApiVersion(1.0);
group.MapPut("{productId}/displayed", ChangeDisplayedAsync)
.WithDisplayName("Change Product Display")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("{productId}/cost", ChangeCostAsync)
.WithDisplayName("Change Product Cost")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0);
group.MapGet("{productId}/comment",GetProductCommentsAsync)
.WithDisplayName("Get Product Comments")
.HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.WithDisplayName("Delete Product")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageProducts))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }
private async Task<IResult> GetProductCommentsAsync([FromQuery] int page, [FromQuery]int count, [FromRoute] Guid productId, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetCommentsQuery(page, count, productId), cancellationToken));
// GET:Get All Entity // GET:Get All Entity
public async Task<IResult> GetAllAsync([FromQuery] int page, public async Task<IResult> GetAllAsync([FromQuery] int page, [FromQuery]string? productName, [FromQuery] QuerySortBy? sortBy, [FromQuery] Guid? categoryId, [FromQuery] bool? specialOffer, [FromQuery] Guid[]? brandIds , [FromQuery]double? minPrice , [FromQuery] double? maxPrice, [FromQuery]bool? isActive, IMediator mediator, CancellationToken cancellationToken)
[FromQuery] string? productName,
[FromQuery] QuerySortBy? sortBy,
[FromQuery] Guid? categoryId,
[FromQuery] bool? specialOffer,
[FromQuery] Guid[]? brandIds,
[FromQuery] double? minPrice,
[FromQuery] double? maxPrice,
[FromQuery] bool? isActive,
IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetProductsQuery(Page: page, SpecialOffer: specialOffer, SortBy: sortBy ?? 0 ,ProductName: productName, CategoryId: categoryId ?? default , BrandIds: brandIds , MinPrice: minPrice ?? -1 , MaxPrice:maxPrice ?? 0,IsActive:isActive),cancellationToken)); => TypedResults.Ok(await mediator.Send(new GetProductsQuery(Page: page, SpecialOffer: specialOffer, SortBy: sortBy ?? 0 ,ProductName: productName, CategoryId: categoryId ?? default , BrandIds: brandIds , MinPrice: minPrice ?? -1 , MaxPrice:maxPrice ?? 0,IsActive:isActive),cancellationToken));
// GET:Get An Entity By Id // GET:Get An Entity By Id
@ -82,17 +53,9 @@ public class ProductController : ICarterModule
CancellationToken cancellationToken) CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request, cancellationToken)); => TypedResults.Ok(await mediator.Send(request, cancellationToken));
// PUT:Update Entity
public async Task<IResult> GetSubProductsAsync(Guid productId, IMediator mediator,
CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetSubProductsQuery(productId), cancellationToken));
public async Task<IResult> ChangeDisplayedAsync(Guid productId, [FromQuery]bool beDisplayed, [FromServices] IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> ChangeDisplayedAsync(Guid productId, [FromQuery]bool beDisplayed, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new ChangeProductDisplayedCommand(productId, beDisplayed), cancellationToken)); => TypedResults.Ok(await mediator.Send(new ChangeProductDisplayedCommand(productId, beDisplayed), cancellationToken));
public async Task<IResult> ChangeCostAsync(Guid productId, [FromQuery] double cost, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new ChangeProductCostCommand(productId, cost), cancellationToken));
// DELETE:Delete Entity // DELETE:Delete Entity
public async Task<IResult> Delete(Guid id, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> Delete(Guid id, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new DeleteProductCommand(id), cancellationToken)); => TypedResults.Ok(await mediator.Send(new DeleteProductCommand(id), cancellationToken));

View File

@ -1,50 +1,50 @@
namespace Netina.Api.Controllers; namespace Netina.Api.Controllers;
public class CommentController : ICarterModule public class ProductReviewController : ICarterModule
{ {
public void AddRoutes(IEndpointRouteBuilder app) public void AddRoutes(IEndpointRouteBuilder app)
{ {
var group = app.NewVersionedApi("Comments") var group = app.NewVersionedApi("ProductReview")
.MapGroup("api/comment"); .MapGroup("product/review");
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Comment") .WithDisplayName("GetOneAsync")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllReviews,ApplicationPermission.ManageReview)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllReviews,ApplicationPermission.ManageReview))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Comments") .WithDisplayName("GetAllAsync")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllReviews, ApplicationPermission.ManageReview)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllReviews, ApplicationPermission.ManageReview))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", PostAsync) group.MapPost("", PostAsync)
.WithDisplayName("Create Comment") .WithDisplayName("PostReview")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageReview, ApplicationPermission.AddReview))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("confirm/{id}", ConfirmAsync) group.MapPut("confirm/{id}", ConfirmAsync)
.WithDisplayName("Confirm Comment") .WithDisplayName("ConfirmAsync")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ConfirmReview, ApplicationPermission.ManageReview)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ConfirmReview, ApplicationPermission.ManageReview))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", DeleteAsync) group.MapDelete("{id}", DeleteAsync)
.WithDisplayName("Delete Comment") .WithDisplayName("DeleteAsync")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageReview)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageReview))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }
public async Task<IResult> GetAllAsync([FromQuery] int page, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> GetAllAsync([FromQuery] int page, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetCommentsQuery(page), cancellationToken)); => TypedResults.Ok(await mediator.Send(new GetReviewsQuery(page), cancellationToken));
public async Task<IResult> GetAsync(Guid id, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> GetAsync(Guid id, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetCommentQuery(id), cancellationToken)); => TypedResults.Ok(await mediator.Send(new GetReviewQuery(id), cancellationToken));
public async Task<IResult> PostAsync(CreateCommentCommand request, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> PostAsync(CreateReviewCommand request, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request, cancellationToken)); => TypedResults.Ok(await mediator.Send(request, cancellationToken));
public async Task<IResult> ConfirmAsync(Guid id, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> ConfirmAsync(Guid id, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new ConfirmCommentCommand(id), cancellationToken)); => TypedResults.Ok(await mediator.Send(new ConfirmReviewCommand(id), cancellationToken));
public async Task<IResult> DeleteAsync(Guid id, IMediator mediator, CancellationToken cancellationToken) public async Task<IResult> DeleteAsync(Guid id, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new DeleteCommentCommand(id), cancellationToken)); => TypedResults.Ok(await mediator.Send(new DeleteReviewCommand(id), cancellationToken));
} }

View File

@ -11,12 +11,12 @@ public class RoleController : ICarterModule
.MapGroup($"api/user/role"); .MapGroup($"api/user/role");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Roles") .WithDisplayName("GetAllRoles")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewRoles, ApplicationPermission.ManageRoles)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewRoles, ApplicationPermission.ManageRoles))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("permission", GetAllPermissions) group.MapGet("permission", GetAllPermissions)
.WithDisplayName("Get Permissions") .WithDisplayName("GetAllPermissions")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewRoles, ApplicationPermission.ManageRoles)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewRoles, ApplicationPermission.ManageRoles))
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -26,17 +26,14 @@ public class RoleController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", Post) group.MapPost("", Post)
.WithDisplayName("Create Role")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.WithDisplayName("Update Role")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.WithDisplayName("Delete Role")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -13,7 +13,7 @@ public class ScraperController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("digi/{productId}", AddProductToShopAsync) group.MapPost("digi/{productId}", AddProductToShopAsync)
.WithDisplayName("Add DigiProduct To Shop") .WithDisplayName("AddProductToShop")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -10,19 +10,19 @@ public class SearchController : ICarterModule
group.MapGet("/thumb", SearchThumbAsync) group.MapGet("/thumb", SearchThumbAsync)
.WithDisplayName("Thumb Search") .WithDisplayName("Thumb Search Async")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("zarehbin", ZarehbinAsync) group.MapGet("zarehbin", ZarehbinAsync)
.WithDisplayName("Get Zarehbin Product") .WithDisplayName("Search Async")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("torob", TorobAsync) group.MapGet("torob", TorobAsync)
.WithDisplayName("Get Torob Product") .WithDisplayName("Get Torob Product Async")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("emalls", EmallsAsync) group.MapGet("emalls", EmallsAsync)
.WithDisplayName("Get Emalls Product") .WithDisplayName("Get Emalls Product Async")
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -2,11 +2,17 @@
using Netina.Domain.Entities.Blogs; using Netina.Domain.Entities.Blogs;
namespace Netina.Api.Controllers; namespace Netina.Api.Controllers;
public class SeedController(IWebHostEnvironment environment) : ICarterModule public class SeedController : ICarterModule
{ {
private readonly IWebHostEnvironment _environment;
public SeedController(IWebHostEnvironment environment)
{
_environment = environment;
}
public void AddRoutes(IEndpointRouteBuilder app) public void AddRoutes(IEndpointRouteBuilder app)
{ {
if (environment.IsDevelopment()) if (_environment.IsDevelopment())
{ {
var group = app.NewVersionedApi("Seed") var group = app.NewVersionedApi("Seed")
.MapGroup("api/seed"); .MapGroup("api/seed");
@ -72,14 +78,13 @@ public class SeedController(IWebHostEnvironment environment) : ICarterModule
var baseCat = await mediator.Send(new CreateProductCategoryCommand("دسته بندی نشده", "محصولات دسته بندی نشده", var baseCat = await mediator.Send(new CreateProductCategoryCommand("دسته بندی نشده", "محصولات دسته بندی نشده",
true, true,
default, default,
new List<StorageFileSDto>(), new List<StorageFileSDto>()),cancellationToken);
new Dictionary<string, string>(),
new Dictionary<string, string>()),cancellationToken);
categories.Add(0,baseCat); categories.Add(0,baseCat);
foreach (var requestDto in request) foreach (var requestDto in request)
{ {
var lDto = await mediator.Send(new CreateProductCategoryCommand(requestDto.Name,requestDto.Description,true,default, var lDto = await mediator.Send(new CreateProductCategoryCommand(requestDto.Name,requestDto.Description,true,default,
new List<StorageFileSDto>(),new Dictionary<string, string>(),new Dictionary<string, string>()), cancellationToken);
new List<StorageFileSDto>()), cancellationToken);
categories.Add(requestDto.BaseCategoryId,lDto); categories.Add(requestDto.BaseCategoryId,lDto);
} }
@ -92,18 +97,13 @@ public class SeedController(IWebHostEnvironment environment) : ICarterModule
if (key != "kKAYskyG8xPxKnJrHkuYxub4Ao2bnz7AOmNtwDT0RaqzaG7ZvbvaP29tCrC8wJ823RczJFXOIQT2bDOec4F38A==") if (key != "kKAYskyG8xPxKnJrHkuYxub4Ao2bnz7AOmNtwDT0RaqzaG7ZvbvaP29tCrC8wJ823RczJFXOIQT2bDOec4F38A==")
throw new AppException("Key is not valid", ApiResultStatusCode.UnAuthorized); throw new AppException("Key is not valid", ApiResultStatusCode.UnAuthorized);
Dictionary<int, Guid> brands = new Dictionary<int, Guid>(); Dictionary<int, Guid> brands = new Dictionary<int, Guid>();
var baseBrand = await mediator.Send(new CreateBrandCommand("بدون برند","NoBrand", var baseBrand = await mediator.Send(new CreateBrandCommand("بدون برند","NoBrand", "محصولات بدون برند", false,string.Empty,
"محصولات بدون برند", new List<StorageFileSDto>()), cancellationToken);
false,
string.Empty,
new List<StorageFileSDto>(),
new Dictionary<string, string>(),
new Dictionary<string, string>()), cancellationToken);
brands.Add(0, baseBrand); brands.Add(0, baseBrand);
foreach (var requestDto in request) foreach (var requestDto in request)
{ {
var sDto = await mediator.Send(new CreateBrandCommand(requestDto.Name,string.Empty, requestDto.Description, false, var sDto = await mediator.Send(new CreateBrandCommand(requestDto.Name,string.Empty, requestDto.Description, false,
string.Empty, new List<StorageFileSDto>(),new Dictionary<string, string>(),new Dictionary<string, string>()), cancellationToken); string.Empty, new List<StorageFileSDto>()), cancellationToken);
brands.Add(requestDto.BaseBrandId,sDto); brands.Add(requestDto.BaseBrandId,sDto);
} }
@ -126,7 +126,7 @@ public class SeedController(IWebHostEnvironment environment) : ICarterModule
seedBlogRequestDto.CategoryId = noCategory.Id; seedBlogRequestDto.CategoryId = noCategory.Id;
} }
var ent = Blog.Create(seedBlogRequestDto.Title, seedBlogRequestDto.Slug, seedBlogRequestDto.Content, seedBlogRequestDto.Tags, seedBlogRequestDto.ReadingTime, var ent = Blog.Create(seedBlogRequestDto.Title, seedBlogRequestDto.Slug, seedBlogRequestDto.Content, seedBlogRequestDto.Tags, seedBlogRequestDto.ReadingTime,
seedBlogRequestDto.Summery, seedBlogRequestDto.IsSuggested, seedBlogRequestDto.CategoryId,default); seedBlogRequestDto.Summery, seedBlogRequestDto.IsSuggested, seedBlogRequestDto.CategoryId);
foreach (var storageFileSDto in seedBlogRequestDto.Files) foreach (var storageFileSDto in seedBlogRequestDto.Files)
{ {

View File

@ -15,7 +15,7 @@ public class SettingController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("{settingName}", PostSettingAsync) group.MapPost("{settingName}", PostSettingAsync)
.WithDisplayName("Create Setting") .WithDisplayName("PostSettingAsync")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageSettings)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageSettings))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -9,7 +9,7 @@ public class ShippingController : ICarterModule
.MapGroup($"api/warehouse/shipping"); .MapGroup($"api/warehouse/shipping");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Shipping") .WithDisplayName("GetAllShipping")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("{id}", GetAsync) group.MapGet("{id}", GetAsync)
@ -18,17 +18,14 @@ public class ShippingController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", Post) group.MapPost("", Post)
.WithDisplayName("Create Shipping")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShipping)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShipping))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.WithDisplayName("Update Shipping")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShipping)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShipping))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.WithDisplayName("Delete Shipping")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShipping)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShipping))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -1,40 +0,0 @@
namespace Netina.Api.Controllers;
public class SubProductController : ICarterModule
{
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("SubProduct")
.MapGroup($"api/sub/product");
group.MapPost("", PostAsync)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Create SubProduct")
.HasApiVersion(1.0);
group.MapPut("", PutAsync)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Update SubProduct")
.HasApiVersion(1.0);
group.MapDelete("{id}", DeleteAsync)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs))
.WithDisplayName("Delete SubProduct")
.HasApiVersion(1.0);
}
// POST:Create Entity
private async Task<IResult> PostAsync([FromBody] CreateSubProductCommand request, IMediator mediator,
CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request, cancellationToken));
// PUT:Update Entity
private async Task<IResult> PutAsync([FromBody] UpdateSubProductCommand request, IMediator mediator,
CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(request, cancellationToken));
// DELETE:Delete Entity
private async Task<IResult> DeleteAsync(Guid id, IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new DeleteSubProductCommand(id), cancellationToken));
}

View File

@ -13,7 +13,7 @@ public class UserAddressController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", PostAddressesAsync) group.MapPost("", PostAddressesAsync)
.WithDisplayName("Create Addresses") .WithDisplayName("Post Addresses")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser())
.HasApiVersion(1.0); .HasApiVersion(1.0);

View File

@ -17,7 +17,7 @@ public class UserController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("Get Users") .WithDisplayName("GetAllUsers")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewUsers, ApplicationPermission.ManageUsers)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewUsers, ApplicationPermission.ManageUsers))
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -27,7 +27,7 @@ public class UserController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("/order", GetUserOrdersAsync) group.MapGet("/order", GetUserOrdersAsync)
.WithDisplayName("Get UserOrders By JWT") .WithDisplayName("GetUserOrders")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewMineOrders)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewMineOrders))
.HasApiVersion(1.0); .HasApiVersion(1.0);
@ -42,17 +42,14 @@ public class UserController : ICarterModule
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPost("", Post) group.MapPost("", Post)
.WithDisplayName("Create User")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageUsers)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageUsers))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapPut("", Put) group.MapPut("", Put)
.WithDisplayName("Update User")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageUsers)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageUsers))
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapDelete("{id}", Delete) group.MapDelete("{id}", Delete)
.WithDisplayName("Delete User")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageUsers)) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageUsers))
.HasApiVersion(1.0); .HasApiVersion(1.0);
} }

View File

@ -1,7 +1,4 @@
using Netina.Domain.Enums; namespace Netina.Api.Controllers;
using Netina.Domain.MartenEntities.Settings;
namespace Netina.Api.Controllers;
public class WebSiteController:ICarterModule public class WebSiteController:ICarterModule
{ {
@ -12,38 +9,8 @@ public class WebSiteController : ICarterModule
group.MapGet("/navbar", GetNavBarItemsAsync) group.MapGet("/navbar", GetNavBarItemsAsync)
.WithDisplayName("Get NavBar Items") .WithDisplayName("Get NavBar Items")
.HasApiVersion(1.0); .HasApiVersion(1.0);
group.MapGet("/catelog", GetCatalogAsync)
.WithDisplayName("Get Catalog Items")
.HasApiVersion(1.0);
group.MapGet("/banner", GetBannerAsync)
.WithDisplayName("Get Banner Items")
.HasApiVersion(1.0);
} }
private async Task<IResult> GetNavBarItemsAsync([FromServices] IMediator mediator, CancellationToken cancellationToken) private async Task<IResult> GetNavBarItemsAsync([FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(await mediator.Send(new GetWebSiteNavBarCommand(),cancellationToken)); => TypedResults.Ok(await mediator.Send(new GetWebSiteNavBarCommand(),cancellationToken));
private async Task<IResult> GetCatalogAsync([FromServices] ISettingService settingService, CancellationToken cancellationToken)
{
var setting = await settingService.GetSettingAsync(nameof(PersonalizationSetting), cancellationToken);
if (setting is PersonalizationSetting personalizationSetting)
{
return TypedResults.Ok(personalizationSetting.Catalog);
}
throw new BaseApiException(ApiResultStatusCode.BadRequest, "Catalogs not found");
}
private async Task<IResult> GetBannerAsync([FromQuery]BannerSection? section,[FromServices] ISettingService settingService, CancellationToken cancellationToken)
{
var setting = await settingService.GetSettingAsync(nameof(PersonalizationSetting), cancellationToken);
if (setting is not PersonalizationSetting personalizationSetting)
throw new BaseApiException(ApiResultStatusCode.BadRequest, "Catalogs not found");
if (section != null)
return TypedResults.Ok(personalizationSetting.Banners.Where(b => b.Section == section));
return TypedResults.Ok(personalizationSetting.Banners);
}
} }

View File

@ -22,6 +22,8 @@ RUN dotnet publish "./Netina.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish
FROM base AS final FROM base AS final
RUN apt-get update
RUN apt-get install-y libgdiplus
WORKDIR /app WORKDIR /app
COPY --from=publish /app/publish . COPY --from=publish /app/publish .

View File

@ -6,54 +6,53 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<AssemblyVersion>1.14.22.42</AssemblyVersion> <AssemblyVersion>1.0.3.3</AssemblyVersion>
<FileVersion>1.14.22.42</FileVersion> <FileVersion>1.0.3.3</FileVersion>
<LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
<PackageReference Include="Asp.Versioning.Http" Version="8.1.0" /> <PackageReference Include="Asp.Versioning.Http" Version="8.1.0" />
<PackageReference Include="Ben.BlockingDetector" Version="0.0.4" /> <PackageReference Include="Ben.BlockingDetector" Version="0.0.4" />
<PackageReference Include="Carter" Version="8.1.0" /> <PackageReference Include="Carter" Version="8.0.0" />
<PackageReference Include="FluentValidation" Version="11.10.0" /> <PackageReference Include="FluentValidation" Version="11.9.0" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.10.0" /> <PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.0" />
<PackageReference Include="MediatR.Extensions.Autofac.DependencyInjection" Version="12.1.0" /> <PackageReference Include="MediatR.Extensions.Autofac.DependencyInjection" Version="12.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Autofac" Version="8.1.0" /> <PackageReference Include="Autofac" Version="8.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Elmah.Io.AspNetCore.Serilog" Version="5.1.23" /> <PackageReference Include="Elmah.Io.AspNetCore.Serilog" Version="5.0.17" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageReference Include="Sentry.Serilog" Version="4.11.0" /> <PackageReference Include="Sentry.Serilog" Version="4.4.0" />
<PackageReference Include="Serilog" Version="4.0.1" /> <PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.PostgreSQL" Version="2.3.0" /> <PackageReference Include="Serilog.Sinks.PostgreSQL" Version="2.3.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="8.0.0" /> <PackageReference Include="Serilog.Sinks.Seq" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.ElmahIo" Version="5.1.43" /> <PackageReference Include="Serilog.Sinks.ElmahIo" Version="5.0.38" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="10.2.0" /> <PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="10.2.0" />
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="10.2.0" /> <PackageReference Include="StackExchange.Redis.Extensions.Core" Version="10.2.0" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="10.2.0" /> <PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="10.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.8.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.1" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" /> <PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="System.Drawing.Common" Version="8.0.8" /> <PackageReference Include="System.Drawing.Common" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -7,7 +7,6 @@ builder.Host.UseSerilog();
LoggerConfig.ConfigureSerilog(); LoggerConfig.ConfigureSerilog();
string env = builder.Environment.IsDevelopment() == true ? "Development" : "Production"; string env = builder.Environment.IsDevelopment() == true ? "Development" : "Production";
builder.Host.UseContentRoot(Directory.GetCurrentDirectory()); builder.Host.UseContentRoot(Directory.GetCurrentDirectory());
if (builder.Environment.IsDevelopment()) if (builder.Environment.IsDevelopment())
{ {
string projectName = "Vesmeh"; string projectName = "Vesmeh";
@ -42,6 +41,7 @@ builder.Services.AddMarten(configuration,builder.Environment);
builder.Services.AddCarter(); builder.Services.AddCarter();
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("NjU5MUAzMTM5MmUzMTJlMzBmYlFPZXRJVThMS20zaFlBdjdKMnlKeGJRQng4b0lURDZ1Rk40akFHbnVrPQ==");
builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
@ -96,12 +96,12 @@ builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
app.UseCustomSwagger(siteSetting.BaseUrl); //app.UseCustomSwagger(siteSetting.BaseUrl);
app.UseSwagger();
app.MapScalarUi(); app.MapScalarUi();
//app.UseSwagger();
//app.UseSwaggerUI(); //app.UseSwaggerUI();
if (app.Environment.IsProduction()) if (app.Environment.IsProduction())

View File

@ -1 +0,0 @@
9167d171-2373-44c9-9fa5-a91858e9854d

View File

@ -3,17 +3,24 @@ using Netina.Repository.Abstracts;
namespace Netina.Api.Services; namespace Netina.Api.Services;
public class CurrentUserService(IHttpContextAccessor httpContextAccessor) : ICurrentUserService public class CurrentUserService : ICurrentUserService
{ {
public string? UserId => httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); private readonly IHttpContextAccessor _httpContextAccessor;
public string? RoleName => httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Role);
public string? UserName => httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Name); public CurrentUserService(IHttpContextAccessor httpContextAccessor)
public string? DeviceId => GetDeviceId(httpContextAccessor.HttpContext); {
_httpContextAccessor = httpContextAccessor;
}
public string? UserId => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
public string? RoleName => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Role);
public string? UserName => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Name);
public string? DeviceId => GetDeviceId(_httpContextAccessor.HttpContext);
public bool IsAuthorized => GetAuthorized(); public bool IsAuthorized => GetAuthorized();
public JwtSecurityToken? JwtToken => GetJwtToken(); public JwtSecurityToken? JwtToken => GetJwtToken();
private JwtSecurityToken? GetJwtToken() private JwtSecurityToken? GetJwtToken()
{ {
var stream = httpContextAccessor.HttpContext?.Request.Headers.Authorization.FirstOrDefault(); var stream = _httpContextAccessor.HttpContext?.Request.Headers.Authorization.FirstOrDefault();
if (stream == null) if (stream == null)
return null; return null;
var handler = new JwtSecurityTokenHandler(); var handler = new JwtSecurityTokenHandler();
@ -21,7 +28,7 @@ public class CurrentUserService(IHttpContextAccessor httpContextAccessor) : ICur
return jsonToken as JwtSecurityToken; return jsonToken as JwtSecurityToken;
} }
public List<string>? Permissions => httpContextAccessor.HttpContext?.User?.FindAll("Permission")?.Select(c => c.Value)?.ToList(); public List<string>? Permissions => _httpContextAccessor.HttpContext?.User?.FindAll("Permission")?.Select(c => c.Value)?.ToList();
private string? GetDeviceId(HttpContext? context) private string? GetDeviceId(HttpContext? context)
{ {
@ -45,9 +52,9 @@ public class CurrentUserService(IHttpContextAccessor httpContextAccessor) : ICur
private bool GetAuthorized() private bool GetAuthorized()
{ {
if (httpContextAccessor.HttpContext?.User.Identity == null) if (_httpContextAccessor.HttpContext?.User.Identity == null)
return false; return false;
return httpContextAccessor.HttpContext.User.Identity.IsAuthenticated; return _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated;
} }

View File

@ -1,4 +1,7 @@
namespace Netina.Api.WebFramework.Bases; using Netina.Common.Models.Api;
using Netina.Core.Models.Api;
namespace Netina.Api.WebFramework.Bases;
public class ApiResultFactory public class ApiResultFactory
{ {

View File

@ -1,13 +1,23 @@
namespace Netina.Api.WebFramework.Bases; using Netina.Common.Models.Entity;
using Netina.Common.Models.Exception;
using Netina.Common.Models.Mapper;
using Netina.Repository.Repositories.Base.Contracts;
namespace Netina.Api.WebFramework.Bases;
public class CrudEndpoint<TEntity, TGetAllQuery, TGetOneQuery, TCreateCommand, TUpdateCommand, TDeleteCommand>( public class CrudEndpoint<TEntity,TGetAllQuery,TGetOneQuery,TCreateCommand,TUpdateCommand,TDeleteCommand> where TEntity : ApiEntity, new()
string endpointName)
where TEntity : ApiEntity, new()
{ {
private readonly string _endpointName;
public CrudEndpoint(string endpointName)
{
_endpointName = endpointName;
}
public virtual void AddRoutes(IEndpointRouteBuilder app) public virtual void AddRoutes(IEndpointRouteBuilder app)
{ {
var group = app.NewVersionedApi(endpointName).MapGroup($"api/{endpointName}"); var group = app.NewVersionedApi(_endpointName).MapGroup($"api/{_endpointName}");
group.MapGet("", GetAllAsync) group.MapGet("", GetAllAsync)
.WithDisplayName("GetAll") .WithDisplayName("GetAll")
@ -73,11 +83,16 @@ public class BaseController : ControllerBase
} }
[Authorize(AuthenticationSchemes = "Bearer")] [Authorize(AuthenticationSchemes = "Bearer")]
public class CrudController<TDto, TEntity>(IRepositoryWrapper repositoryWrapper) : BaseController public class CrudController<TDto, TEntity> : BaseController
where TDto : BaseDto<TDto, TEntity>, new() where TDto : BaseDto<TDto, TEntity>, new()
where TEntity : ApiEntity, new() where TEntity : ApiEntity, new()
{ {
protected readonly IRepositoryWrapper _repositoryWrapper = repositoryWrapper; protected readonly IRepositoryWrapper _repositoryWrapper;
public CrudController(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
// GET:Get All Entity // GET:Get All Entity
[HttpGet] [HttpGet]
@ -153,10 +168,15 @@ public class CrudController<TDto, TEntity>(IRepositoryWrapper repositoryWrapper)
} }
[Authorize(AuthenticationSchemes = "Bearer")] [Authorize(AuthenticationSchemes = "Bearer")]
public class CrudController<TEntity>(IRepositoryWrapper repositoryWrapper) : BaseController public class CrudController<TEntity> : BaseController
where TEntity : ApiEntity, new() where TEntity : ApiEntity, new()
{ {
protected readonly IRepositoryWrapper _repositoryWrapper = repositoryWrapper; protected readonly IRepositoryWrapper _repositoryWrapper;
public CrudController(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
// GET:Get All Entity // GET:Get All Entity
[HttpGet] [HttpGet]

View File

@ -1,4 +1,6 @@
namespace Netina.Api.WebFramework.Configurations; using Netina.Infrastructure.Models;
namespace Netina.Api.WebFramework.Configurations;
public static class LoggerConfig public static class LoggerConfig
{ {

View File

@ -52,14 +52,14 @@ public static class ServiceExtensions
{ {
new() new()
{ {
Hosts = Hosts = new[]
[ {
new RedisHost new RedisHost
{ {
Port = siteSettings.MasterRedisConfiguration.Port, Port = siteSettings.MasterRedisConfiguration.Port,
Host = siteSettings.MasterRedisConfiguration.Host Host = siteSettings.MasterRedisConfiguration.Host
} }
], },
Password = siteSettings.MasterRedisConfiguration.Password, Password = siteSettings.MasterRedisConfiguration.Password,
Ssl = false Ssl = false
} }

View File

@ -1,4 +1,7 @@
using Refit; using Netina.Common.Models.Api;
using Netina.Common.Models.Exception;
using Netina.Core.Models.Api;
using Refit;
namespace Netina.Api.WebFramework.MiddleWares; namespace Netina.Api.WebFramework.MiddleWares;
@ -10,11 +13,22 @@ public static class ExceptionHandlerMiddlewareExtensions
} }
} }
public class ExceptionHandlerMiddleware( public class ExceptionHandlerMiddleware
{
private readonly IWebHostEnvironment _env;
private readonly ILogger<ExceptionHandlerMiddleware> _logger;
private readonly RequestDelegate _next;
public ExceptionHandlerMiddleware(
RequestDelegate next, RequestDelegate next,
IWebHostEnvironment env, IWebHostEnvironment env,
ILogger<ExceptionHandlerMiddleware> logger) ILogger<ExceptionHandlerMiddleware> logger)
{ {
_next = next;
_env = env;
_logger = logger;
}
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
string message = null; string message = null;
@ -23,17 +37,15 @@ public class ExceptionHandlerMiddleware(
try try
{ {
await next(context); await _next(context);
} }
catch (BaseApiException exception) catch (BaseApiException exception)
{ {
logger.LogError(exception, exception.Message); _logger.LogError(exception, exception.Message);
httpStatusCode = exception.ApiStatusCode == ApiResultStatusCode.NotFound ? HttpStatusCode.NotFound : httpStatusCode = exception.HttpStatusCode;
exception.ApiStatusCode == ApiResultStatusCode.BadRequest ?
HttpStatusCode.BadRequest : exception.HttpStatusCode;
apiStatusCode = exception.ApiStatusCode; apiStatusCode = exception.ApiStatusCode;
if (env.IsDevelopment()) if (_env.IsDevelopment())
{ {
var dic = new Dictionary<string, string> var dic = new Dictionary<string, string>
{ {
@ -71,19 +83,19 @@ public class ExceptionHandlerMiddleware(
} }
catch (SecurityTokenExpiredException exception) catch (SecurityTokenExpiredException exception)
{ {
logger.LogError(exception, exception.Message); _logger.LogError(exception, exception.Message);
SetUnAuthorizeResponse(exception); SetUnAuthorizeResponse(exception);
await WriteToResponseAsync(); await WriteToResponseAsync();
} }
catch (UnauthorizedAccessException exception) catch (UnauthorizedAccessException exception)
{ {
logger.LogError(exception, exception.Message); _logger.LogError(exception, exception.Message);
SetUnAuthorizeResponse(exception); SetUnAuthorizeResponse(exception);
await WriteToResponseAsync(); await WriteToResponseAsync();
} }
catch (ApiException apiException) catch (ApiException apiException)
{ {
logger.LogError(apiException, apiException.Message); _logger.LogError(apiException, apiException.Message);
httpStatusCode = HttpStatusCode.InternalServerError; httpStatusCode = HttpStatusCode.InternalServerError;
apiStatusCode = ApiResultStatusCode.RefitError; apiStatusCode = ApiResultStatusCode.RefitError;
@ -94,9 +106,9 @@ public class ExceptionHandlerMiddleware(
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, exception.Message); _logger.LogError(exception, exception.Message);
if (env.IsDevelopment()) if (_env.IsDevelopment())
{ {
if (exception?.InnerException?.Message != null) if (exception?.InnerException?.Message != null)
{ {
@ -133,7 +145,7 @@ public class ExceptionHandlerMiddleware(
}); });
if (httpStatusCode == HttpStatusCode.InternalServerError) if (httpStatusCode == HttpStatusCode.InternalServerError)
context.Response.StatusCode = (int)HttpStatusCode.BadRequest; context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
else else
context.Response.StatusCode = (int)httpStatusCode; context.Response.StatusCode = (int)httpStatusCode;
context.Response.ContentType = "application/json"; context.Response.ContentType = "application/json";
@ -174,7 +186,7 @@ public class ExceptionHandlerMiddleware(
httpStatusCode = HttpStatusCode.Unauthorized; httpStatusCode = HttpStatusCode.Unauthorized;
apiStatusCode = ApiResultStatusCode.UnAuthorized; apiStatusCode = ApiResultStatusCode.UnAuthorized;
if (env.IsDevelopment()) if (_env.IsDevelopment())
{ {
var dic = new Dictionary<string, string> var dic = new Dictionary<string, string>
{ {

View File

@ -8,19 +8,28 @@ public static class PerformanceMiddlewareExtensions
} }
} }
public class PerformanceMiddleware( public class PerformanceMiddleware
{
private readonly ILogger<ExceptionHandlerMiddleware> _logger;
private readonly RequestDelegate _next;
private readonly Stopwatch _timer;
public PerformanceMiddleware(
RequestDelegate next, RequestDelegate next,
ILogger<ExceptionHandlerMiddleware> logger) ILogger<ExceptionHandlerMiddleware> logger)
{ {
private readonly Stopwatch _timer = new(); _next = next;
_logger = logger;
_timer = new Stopwatch();
}
public async System.Threading.Tasks.Task Invoke(HttpContext context) public async System.Threading.Tasks.Task Invoke(HttpContext context)
{ {
_timer.Start(); _timer.Start();
await next(context); await _next(context);
_timer.Stop(); _timer.Stop();
var elapsedMilliseconds = _timer.ElapsedMilliseconds; var elapsedMilliseconds = _timer.ElapsedMilliseconds;
logger.LogWarning($"REQUEST TIMER : {elapsedMilliseconds}"); _logger.LogWarning($"REQUEST TIMER : {elapsedMilliseconds}");
} }
} }

View File

@ -27,7 +27,7 @@ public static class ScalarUiConfiguration
<!-- Optional: You can set a full configuration object like this: --> <!-- Optional: You can set a full configuration object like this: -->
<script> <script>
var configuration = { var configuration = {
theme: 'mars', theme: 'bluePlanet',
} }
document.getElementById('api-reference').dataset.configuration = document.getElementById('api-reference').dataset.configuration =

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Netina.Common.Extensions;
using Pluralize.NET; using Pluralize.NET;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;
@ -18,8 +19,8 @@ public static class SwaggerConfiguration
new OpenApiInfo new OpenApiInfo
{ {
Version = "v1", Version = "v1",
Title = "Netina Api Document", Title = "iGarson Api Dacument",
Description = "Netina api for netina clients , like shops , websites and apps", Description = "iGarson api for clients that wana use",
License = new OpenApiLicense { Name = "Vira Safir Fanavar " }, License = new OpenApiLicense { Name = "Vira Safir Fanavar " },
Contact = new OpenApiContact Contact = new OpenApiContact
{ {
@ -138,12 +139,17 @@ public class SetVersionInPaths : IDocumentFilter
} }
} }
public class UnauthorizedResponsesOperationFilter( public class UnauthorizedResponsesOperationFilter : IOperationFilter
bool includeUnauthorizedAndForbiddenResponses,
string schemeName = "Bearer")
: IOperationFilter
{ {
private readonly string schemeName = schemeName; private readonly bool includeUnauthorizedAndForbiddenResponses;
private readonly string schemeName;
public UnauthorizedResponsesOperationFilter(bool includeUnauthorizedAndForbiddenResponses,
string schemeName = "Bearer")
{
this.includeUnauthorizedAndForbiddenResponses = includeUnauthorizedAndForbiddenResponses;
this.schemeName = schemeName;
}
public void Apply(OpenApiOperation operation, OperationFilterContext context) public void Apply(OpenApiOperation operation, OperationFilterContext context)
{ {

View File

@ -1,23 +1,14 @@
using System.Net; using System.Web;
using System.Web; using System.Xml.Linq;
namespace Netina.Common.Extensions namespace Netina.Common.Extensions
{ {
public static class StringExtensions public static class StringExtensions
{ {
public static bool IsNullOrEmpty(this string value)
=> string.IsNullOrEmpty(value);
public static string GetSlug(string title) public static string GetSlug(string title)
{ {
var splits = title.Split("/"); return HttpUtility.UrlEncode(title.Replace(' ', '-'));
string outPut = string.Empty;
foreach (var split in splits)
outPut = outPut.IsNullOrEmpty() ? split : string.Concat(outPut, "/", WebUtility.UrlEncode( split.Replace(' ', '-')));
return outPut;
} }
public static string ToPriceWhitPriceType(this long price, string priceType) public static string ToPriceWhitPriceType(this long price, string priceType)
{ {
return price.ToString("N0") + " " + priceType; return price.ToString("N0") + " " + priceType;

View File

@ -19,23 +19,23 @@ public class MartenEntity : IMartenEntity
//public bool Equals(ApiEntity other) public bool Equals(ApiEntity other)
//{ {
// if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
// if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
// return Id.Equals(other.Id); return Id.Equals(other.Id);
//} }
//public override bool Equals(object obj) public override bool Equals(object obj)
//{ {
// if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(null, obj)) return false;
// if (ReferenceEquals(this, obj)) return true; if (ReferenceEquals(this, obj)) return true;
// if (obj.GetType() != this.GetType()) return false; if (obj.GetType() != this.GetType()) return false;
// return Equals((ApiEntity)obj); return Equals((ApiEntity)obj);
//} }
//public override int GetHashCode() public override int GetHashCode()
//{ {
// return Id.GetHashCode(); return Id.GetHashCode();
//} }
} }

View File

@ -3,14 +3,15 @@
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
public class PageClassDisplay : Attribute public class PageClassDisplay : Attribute
{ {
private readonly string _name;
private readonly string _description; private readonly string _description;
private readonly string _name;
public PageClassDisplay(string name, string description) public PageClassDisplay(string name, string description)
{ {
_name = name; _name = name;
_description = description; _description = description;
} }
public string GetName() public string GetName()
{ {
return _name; return _name;

View File

@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
@ -12,12 +11,12 @@
<PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" /> <PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />
</ItemGroup> </ItemGroup>
<!--<PropertyGroup> <!--<PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>10</LangVersion>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>

View File

@ -2,12 +2,8 @@
public interface IPageService : IScopedDependency public interface IPageService : IScopedDependency
{ {
Task<BasePageLDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default); Task<BasePageSDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default);
Task<List<BasePageSDto>> GetPagesAsync(CancellationToken cancellationToken = default); Task<List<BasePageSDto>> GetPagesAsync(CancellationToken cancellationToken = default);
Task<bool> CreatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default); Task<bool> CreatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default);
Task<bool> UpdatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default);
Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default); Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default);
Task<string> CheckRedirectAsync(string oldUrl, CancellationToken cancellationToken);
Task<bool> CheckDeletedAsync(string url, CancellationToken cancellationToken);
} }

View File

@ -1,7 +1,18 @@
namespace Netina.Core.BaseServices; namespace Netina.Core.BaseServices;
public class AccountService( public class AccountService : IAccountService
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _userSignInManager;
private readonly IJwtService _jwtService;
private readonly ICurrentUserService _currentUserService;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ISmsService _smsService;
private readonly IUserService _managerUserService;
public AccountService(
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> userSignInManager, SignInManager<ApplicationUser> userSignInManager,
IJwtService jwtService, IJwtService jwtService,
@ -9,24 +20,34 @@ public class AccountService(
IRepositoryWrapper repositoryWrapper, IRepositoryWrapper repositoryWrapper,
ISmsService smsService, ISmsService smsService,
IUserService managerUserService) IUserService managerUserService)
: IAccountService
{ {
_userManager = userManager;
_userSignInManager = userSignInManager;
_jwtService = jwtService;
_currentUserService = currentUserService;
_repositoryWrapper = repositoryWrapper;
_smsService = smsService;
_managerUserService = managerUserService;
}
public async Task<bool> ForgetPasswordAsync(string phoneNumber) public async Task<bool> ForgetPasswordAsync(string phoneNumber)
{ {
var user = await userManager.FindByNameAsync(phoneNumber); var user = await _userManager.FindByNameAsync(phoneNumber);
if (user != null) if (user != null)
{ {
var rand = new Random(DateTime.Now.Millisecond); var rand = new Random(DateTime.Now.Millisecond);
var newPass = rand.Next(1000000, 9000000).ToString(); var newPass = rand.Next(1000000, 9000000).ToString();
if (!user.PhoneNumberConfirmed) if (!user.PhoneNumberConfirmed)
throw new AppException("شماره تلفن شما تایید نشده است و قابلیت استفاده از فراموشی رمز عبور را ندارید"); throw new AppException("شماره تلفن شما تایید نشده است و قابلیت استفاده از فراموشی رمز عبور را ندارید");
var rp = await userManager.RemovePasswordAsync(user); var rp = await _userManager.RemovePasswordAsync(user);
if (!rp.Succeeded) if (!rp.Succeeded)
throw new AppException(string.Join('-', rp.Errors.Select(e => e.Description))); throw new AppException(string.Join('-', rp.Errors.Select(e => e.Description)));
var ap = await userManager.AddPasswordAsync(user, newPass); var ap = await _userManager.AddPasswordAsync(user, newPass);
if (!ap.Succeeded) if (!ap.Succeeded)
throw new AppException(string.Join('-', ap.Errors.Select(e => e.Description))); throw new AppException(string.Join('-', ap.Errors.Select(e => e.Description)));
await smsService.SendForgerPasswordAsync(user.PhoneNumber, newPass); await _smsService.SendForgerPasswordAsync(user.PhoneNumber, newPass);
return true; return true;
} }
@ -35,7 +56,7 @@ public class AccountService(
public async Task<bool> CheckMemberShipAsync(string phoneNumber) public async Task<bool> CheckMemberShipAsync(string phoneNumber)
{ {
var user = await userManager.FindByNameAsync(phoneNumber); var user = await _userManager.FindByNameAsync(phoneNumber);
if (user == null) if (user == null)
return false; return false;
return true; return true;
@ -46,23 +67,23 @@ public class AccountService(
var newPhoneNumber = StringExtensions.CheckPhoneNumber(phoneNumber); var newPhoneNumber = StringExtensions.CheckPhoneNumber(phoneNumber);
if (!PhoneNumberExtensions.CheckPhoneNumber(newPhoneNumber)) if (!PhoneNumberExtensions.CheckPhoneNumber(newPhoneNumber))
throw new AppException("شماره تلفن ارسالی اشتباه است"); throw new AppException("شماره تلفن ارسالی اشتباه است");
var user = await userManager.FindByNameAsync(newPhoneNumber); var user = await _userManager.FindByNameAsync(newPhoneNumber);
if (user == null) if (user == null)
user = await managerUserService.CreateUserAsync(phoneNumber); user = await _managerUserService.CreateUserAsync(phoneNumber);
var token = await userManager.GenerateTwoFactorTokenAsync(user, "Phone"); var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Phone");
await smsService.SendVerifyCodeAsync(newPhoneNumber, token); await _smsService.SendVerifyCodeAsync(newPhoneNumber, token);
return new VerifyCodeResponseDto { SignUpStatus = SignUpStatus.StartSignOn }; return new VerifyCodeResponseDto { SignUpStatus = SignUpStatus.StartSignOn };
} }
public async Task<AccessToken<ApplicationUserSDto>> LoginWithPasswordAsync(string userName, string password, CancellationToken cancellationToken) public async Task<AccessToken<ApplicationUserSDto>> LoginWithPasswordAsync(string userName, string password, CancellationToken cancellationToken)
{ {
var result = await userSignInManager.PasswordSignInAsync(userName, password, false, false); var result = await _userSignInManager.PasswordSignInAsync(userName, password, false, false);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException("رمز عبور یا نام کاربری اشتباه است"); throw new AppException("رمز عبور یا نام کاربری اشتباه است");
var admin = await userManager.FindByNameAsync(userName); var admin = await _userManager.FindByNameAsync(userName);
if (admin == null) if (admin == null)
throw new AppException("نام کاربری یا رمز عبور اشتباه است"); throw new AppException("نام کاربری یا رمز عبور اشتباه است");
return await CompleteLogin(admin, cancellationToken); return await CompleteLogin(admin, cancellationToken);
@ -70,11 +91,11 @@ public class AccountService(
public async Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync(string userName, string verifyCode, CancellationToken cancellationToken) public async Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync(string userName, string verifyCode, CancellationToken cancellationToken)
{ {
var user = await userManager.FindByNameAsync(userName); var user = await _userManager.FindByNameAsync(userName);
if (user == null) if (user == null)
throw new AppException("نام کاربری یا کد ارسالی اشتباه است", ApiResultStatusCode.NotFound); throw new AppException("نام کاربری یا کد ارسالی اشتباه است", ApiResultStatusCode.NotFound);
var verfiyResult = await userManager.VerifyTwoFactorTokenAsync(user, "Phone", verifyCode); var verfiyResult = await _userManager.VerifyTwoFactorTokenAsync(user, "Phone", verifyCode);
if (verifyCode == "859585") if (verifyCode == "859585")
verfiyResult = true; verfiyResult = true;
if (!verfiyResult) if (!verfiyResult)
@ -83,7 +104,7 @@ public class AccountService(
{ {
user.PhoneNumberConfirmed = true; user.PhoneNumberConfirmed = true;
user.SignUpStatus = SignUpStatus.PhoneNumberVerified; user.SignUpStatus = SignUpStatus.PhoneNumberVerified;
var result = await userManager.UpdateAsync(user); var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors)); throw new AppException(string.Join('|', result.Errors));
} }
@ -92,9 +113,9 @@ public class AccountService(
public async Task<AccessToken<ApplicationUserSDto>> CompleteSignUpAsync(SignUpRequestDto requestDto, CancellationToken cancellationToken) public async Task<AccessToken<ApplicationUserSDto>> CompleteSignUpAsync(SignUpRequestDto requestDto, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("User Id is null"); throw new AppException("User Id is null");
var user = await userManager.FindByIdAsync(currentUserService.UserId); var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
if (user == null) if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
if (user.SignUpStatus == SignUpStatus.SignUpCompleted) if (user.SignUpStatus == SignUpStatus.SignUpCompleted)
@ -111,19 +132,19 @@ public class AccountService(
user.FirstName = requestDto.FirstName; user.FirstName = requestDto.FirstName;
user.LastName = requestDto.LastName; user.LastName = requestDto.LastName;
user.SignUpStatus = SignUpStatus.SignUpCompleted; user.SignUpStatus = SignUpStatus.SignUpCompleted;
var result = await userManager.UpdateAsync(user); var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
var roleResult = await userManager.AddToRoleAsync(user, "Customer"); var roleResult = await _userManager.AddToRoleAsync(user, "Customer");
if (!roleResult.Succeeded) if (!roleResult.Succeeded)
throw new AppException(string.Join('|', roleResult.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', roleResult.Errors.Select(e => e.Description)));
repositoryWrapper.SetRepository<Customer>() _repositoryWrapper.SetRepository<Customer>()
.Add(new Customer .Add(new Customer
{ {
UserId = user.Id, UserId = user.Id,
}); });
await repositoryWrapper.SaveChangesAsync(default); await _repositoryWrapper.SaveChangesAsync(default);
return await CompleteLogin(user, cancellationToken); return await CompleteLogin(user, cancellationToken);
} }
@ -132,8 +153,8 @@ public class AccountService(
private async Task<AccessToken<ApplicationUserSDto>> CompleteLogin(ApplicationUser user, CancellationToken cancellationToken) private async Task<AccessToken<ApplicationUserSDto>> CompleteLogin(ApplicationUser user, CancellationToken cancellationToken)
{ {
AccessToken<ApplicationUserSDto> jwt; AccessToken<ApplicationUserSDto> jwt;
var role = await userManager.GetRolesAsync(user); var role = await _userManager.GetRolesAsync(user);
jwt = await jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, role.ToList()); jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, role.ToList());
jwt.User.RoleName = jwt.RoleName; jwt.User.RoleName = jwt.RoleName;
return jwt; return jwt;
} }

View File

@ -2,31 +2,38 @@
namespace Netina.Core.BaseServices; namespace Netina.Core.BaseServices;
public class DashboardService(IRepositoryWrapper repositoryWrapper, UserManager<ApplicationUser> userManager) public class DashboardService : IDashboardService
: IDashboardService
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly UserManager<ApplicationUser> _userManager;
public DashboardService(IRepositoryWrapper repositoryWrapper,UserManager<ApplicationUser> userManager)
{
_repositoryWrapper = repositoryWrapper;
_userManager = userManager;
}
public async Task<HomeDashboardDto> GetHomeDashboardAsyncTask(CancellationToken cancellationToken = default) public async Task<HomeDashboardDto> GetHomeDashboardAsyncTask(CancellationToken cancellationToken = default)
{ {
var response = new HomeDashboardDto var response = new HomeDashboardDto
{ {
BlogsCount = await repositoryWrapper.SetRepository<Blog>() BlogsCount = await _repositoryWrapper.SetRepository<Blog>()
.TableNoTracking .TableNoTracking
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
ProductsCount = await repositoryWrapper.SetRepository<Product>() ProductsCount = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
TodayOrdersCount = await repositoryWrapper.SetRepository<Order>() TodayOrdersCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(o => o.OrderAt.Date == DateTime.Today.Date) .Where(o => o.OrderAt.Date == DateTime.Today.Date)
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
UnSubmittedOrdersCount = await repositoryWrapper.SetRepository<Order>() UnSubmittedOrdersCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(o => o.OrderStatus == OrderStatus.Paid || o.OrderStatus == OrderStatus.Submitted) .Where(o => o.OrderStatus == OrderStatus.Paid || o.OrderStatus == OrderStatus.Submitted)
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
BrandsCount = await repositoryWrapper.SetRepository<Brand>() BrandsCount = await _repositoryWrapper.SetRepository<Brand>()
.TableNoTracking .TableNoTracking
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
SubscribersCount = await userManager.Users.CountAsync(cancellationToken) SubscribersCount = await _userManager.Users.CountAsync(cancellationToken)
}; };
return response; return response;
@ -38,19 +45,19 @@ public class DashboardService(IRepositoryWrapper repositoryWrapper, UserManager<
DateTime endOfThisMonth = startOfThisMonth.AddMonths(1); DateTime endOfThisMonth = startOfThisMonth.AddMonths(1);
var response = new OrderDashboardDto var response = new OrderDashboardDto
{ {
PayedOrdersCount = await repositoryWrapper.SetRepository<Order>() PayedOrdersCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(o=>o.IsPayed && o.OrderStatus==OrderStatus.Paid) .Where(o=>o.IsPayed && o.OrderStatus==OrderStatus.Paid)
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
ThisMonthOrdersCount = await repositoryWrapper.SetRepository<Order>() ThisMonthOrdersCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(s => s.OrderAt.Date >= startOfThisMonth.Date && s.OrderAt.Date < endOfThisMonth.Date) .Where(s => s.OrderAt.Date >= startOfThisMonth.Date && s.OrderAt.Date < endOfThisMonth.Date)
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
TodayOrdersCount = await repositoryWrapper.SetRepository<Order>() TodayOrdersCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(o => o.OrderAt.Date == DateTime.Now.Date) .Where(o => o.OrderAt.Date == DateTime.Now.Date)
.CountAsync(cancellationToken), .CountAsync(cancellationToken),
UnSendOrdersCount = await repositoryWrapper.SetRepository<Order>() UnSendOrdersCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(o => o.IsPayed && o.OrderStatus == OrderStatus.Processing) .Where(o => o.IsPayed && o.OrderStatus == OrderStatus.Processing)
.CountAsync(cancellationToken) .CountAsync(cancellationToken)

View File

@ -1,14 +1,21 @@
namespace Netina.Core.BaseServices; namespace Netina.Core.BaseServices;
public class JwtService( public class JwtService : IJwtService
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly SiteSettings _siteSettings;
public JwtService(
IOptionsSnapshot<SiteSettings> siteSettings, IOptionsSnapshot<SiteSettings> siteSettings,
SignInManager<ApplicationUser> userSignInManager, SignInManager<ApplicationUser> userSignInManager,
RoleManager<ApplicationRole> roleManager) RoleManager<ApplicationRole> roleManager)
: IJwtService
{ {
private readonly SiteSettings _siteSettings = siteSettings.Value; _signInManager = userSignInManager;
_roleManager = roleManager;
_siteSettings = siteSettings.Value;
}
public async Task<AccessToken<TUser>> Generate<TUser>(TUser user) where TUser : ApplicationUser public async Task<AccessToken<TUser>> Generate<TUser>(TUser user) where TUser : ApplicationUser
{ {
var tokenId = StringExtensions.GetId(8); var tokenId = StringExtensions.GetId(8);
@ -82,7 +89,7 @@ public class JwtService(
private async Task<List<Claim>> GetClaims<TUser>(TUser baseUser, string jwtId) where TUser : ApplicationUser private async Task<List<Claim>> GetClaims<TUser>(TUser baseUser, string jwtId) where TUser : ApplicationUser
{ {
var clFac = (await userSignInManager.ClaimsFactory.CreateAsync(baseUser)); var clFac = (await _signInManager.ClaimsFactory.CreateAsync(baseUser));
var claims = new List<Claim>(); var claims = new List<Claim>();
claims.Add(new Claim("JwtID", jwtId)); claims.Add(new Claim("JwtID", jwtId));
claims.Add(new Claim(ClaimTypes.Name, baseUser.UserName)); claims.Add(new Claim(ClaimTypes.Name, baseUser.UserName));
@ -101,10 +108,10 @@ public class JwtService(
foreach (var roleName in roleNames) foreach (var roleName in roleNames)
{ {
var applicationRole = await roleManager.FindByNameAsync(roleName); var applicationRole = await _roleManager.FindByNameAsync(roleName);
if(applicationRole==null) if(applicationRole==null)
continue; continue;
var roleClaims = await roleManager.GetClaimsAsync(applicationRole); var roleClaims = await _roleManager.GetClaimsAsync(applicationRole);
claims.AddRange(roleClaims); claims.AddRange(roleClaims);
claims.Add(new Claim(ClaimTypes.Role, applicationRole.EnglishName)); claims.Add(new Claim(ClaimTypes.Role, applicationRole.EnglishName));
claims.Add(new Claim("RoleId", applicationRole.Id.ToString())); claims.Add(new Claim("RoleId", applicationRole.Id.ToString()));

View File

@ -2,31 +2,42 @@
namespace Netina.Core.BaseServices; namespace Netina.Core.BaseServices;
public class PageService( public class PageService : IPageService
IMartenRepositoryWrapper martenRepositoryWrapperWrapper,
ICurrentUserService currentUserService,
ISettingService settingService)
: IPageService
{ {
public async Task<BasePageLDto> GetPageAsync(Guid? id = null, private readonly IMartenRepositoryWrapper _martenRepositoryWrapper;
string? pageName = null, private readonly ICurrentUserService _currentUserService;
string? pageSlug = null,
string? type = null, public PageService(IMartenRepositoryWrapper martenRepositoryWrapperWrapper, ICurrentUserService currentUserService)
CancellationToken cancellationToken = default) {
_martenRepositoryWrapper = martenRepositoryWrapperWrapper;
_currentUserService = currentUserService;
}
public async Task<BasePageSDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default)
{ {
BasePage? page = null; BasePage? page = null;
if (id != null) if (id != null)
page = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntityAsync(id.Value, cancellationToken); page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(id.Value, cancellationToken);
else if (pageSlug != null) else if (pageSlug != null)
page = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Slug == pageSlug, cancellationToken); page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Slug == pageSlug, cancellationToken);
else if (pageName != null) else if (pageName != null)
page = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Title == pageName, cancellationToken); page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Title == pageName, cancellationToken);
else if (type != null) else if (type != null)
page = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Type == type, cancellationToken); page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Type == type, cancellationToken);
if (page == null) if (page == null)
throw new AppException("Page not found", ApiResultStatusCode.NotFound); throw new AppException("Page not found", ApiResultStatusCode.NotFound);
var dto = page.Adapt<BasePageLDto>(); var entityType = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(page.Type);
var dto = new BasePageSDto
{
Content = page.Content,
Description = page.Description,
Id = page.Id,
IsCustomPage = page.IsCustomPage,
IsHtmlBasePage = page.IsHtmlBasePage,
Title = page.Title,
Slug = page.Slug,
Data = page.Data
};
return dto; return dto;
} }
@ -34,10 +45,22 @@ public class PageService(
public async Task<List<BasePageSDto>> GetPagesAsync(CancellationToken cancellationToken = default) public async Task<List<BasePageSDto>> GetPagesAsync(CancellationToken cancellationToken = default)
{ {
List<BasePageSDto> sDtos = new List<BasePageSDto>(); List<BasePageSDto> sDtos = new List<BasePageSDto>();
var pages = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntitiesAsync(cancellationToken); var pages = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntitiesAsync(cancellationToken);
foreach (var page in pages) foreach (var page in pages)
{ {
var dto = page.Adapt<BasePageSDto>(); var dto = new BasePageSDto
{
Content = page.Content,
Description = page.Description,
Id = page.Id,
IsCustomPage = page.IsCustomPage,
IsHtmlBasePage = page.IsHtmlBasePage,
Title = page.Title,
Slug = page.Slug,
Data = page.Data,
CreatedAt = page.CreatedAt,
ModifiedAt = page.ModifiedAt
};
sDtos.Add(dto); sDtos.Add(dto);
} }
return sDtos; return sDtos;
@ -56,61 +79,23 @@ public class PageService(
Type = entity.Type, Type = entity.Type,
Slug = entity.Slug, Slug = entity.Slug,
CreatedAt = DateTime.Now, CreatedAt = DateTime.Now,
CreatedBy = currentUserService.UserName ?? string.Empty, CreatedBy = _currentUserService.UserName ?? string.Empty
Indexing = entity.Indexing,
Sections = entity.Sections
}; };
if (!basePage.Type.IsNullOrEmpty()) if (!basePage.Type.IsNullOrEmpty())
{ {
var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(entity.Type); var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(entity.Type);
basePage.Data = JsonConvert.SerializeObject(((JsonElement)entity.Data).Deserialize(type)); basePage.Data = JsonConvert.SerializeObject(((JsonElement)entity.Data).Deserialize(type));
} }
await martenRepositoryWrapperWrapper.SetRepository<BasePage>().AddOrUpdateEntityAsync(basePage, cancellationToken); await _martenRepositoryWrapper.SetRepository<BasePage>().AddOrUpdateEntityAsync(basePage, cancellationToken);
return true; return true;
} }
public async Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default) public async Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default)
{ {
var page = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntityAsync(p => p.Id == id, cancellationToken); var page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(p => p.Id == id, cancellationToken);
if (page == null) if (page == null)
throw new AppException("Page not found", ApiResultStatusCode.NotFound); throw new AppException("Page not found", ApiResultStatusCode.NotFound);
await martenRepositoryWrapperWrapper.SetRepository<BasePage>().RemoveEntityAsync(page, cancellationToken); await _martenRepositoryWrapper.SetRepository<BasePage>().RemoveEntityAsync(page, cancellationToken);
return true;
}
public async Task<string> CheckRedirectAsync(string oldUrl, CancellationToken cancellationToken)
{
var setting = await settingService.GetSettingAsync(nameof(PageSetting), cancellationToken);
var oldEncode = StringExtensions.GetSlug(oldUrl);
if (setting is PageSetting pageSetting)
{
var newLink = pageSetting.RedirectItems.FirstOrDefault(f => f.OldUrl.ToLower().Trim() == oldEncode.ToLower().Trim());
if (newLink != null)
{
var response = newLink.NewUrl[0] == '/' ? newLink.NewUrl : $"/{newLink.NewUrl}";
return response;
}
else
throw new BaseApiException(ApiResultStatusCode.NotFound, "Url not found");
}
throw new BaseApiException(ApiResultStatusCode.NotFound, "PageSetting not found");
}
public async Task<bool> CheckDeletedAsync(string url, CancellationToken cancellationToken)
{
var setting = await settingService.GetSettingAsync(nameof(PageSetting), cancellationToken);
if (setting is PageSetting pageSetting)
{
var newLink = pageSetting.DeletedPages.FirstOrDefault(f => f.Url.ToLower().Trim() == url.ToLower().Trim());
return newLink != null;
}
throw new BaseApiException(ApiResultStatusCode.NotFound, "PageSetting not found");
}
public async Task<bool> UpdatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default)
{
var basePage = entity.Adapt<BasePage>();
await martenRepositoryWrapperWrapper.SetRepository<BasePage>().AddOrUpdateEntityAsync(basePage, cancellationToken);
return true; return true;
} }
} }

View File

@ -1,16 +1,21 @@
 
namespace Netina.Core.BaseServices; public class SettingService : ISettingService
public class SettingService(IMartenRepositoryWrapper martenRepositoryWrapper) : ISettingService
{ {
private readonly IMartenRepositoryWrapper _martenRepositoryWrapper;
public SettingService(IMartenRepositoryWrapper martenRepositoryWrapper)
{
_martenRepositoryWrapper = martenRepositoryWrapper;
}
public async Task<object> GetSettingAsync(string settingName, CancellationToken cancellationToken = default) public async Task<object> GetSettingAsync(string settingName, CancellationToken cancellationToken = default)
{ {
var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"Netina.Domain.MartenEntities.Settings.{settingName}"); var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"Netina.Domain.MartenEntities.Settings.{settingName}");
if (type == null) if (type == null)
throw new AppException("Setting not found", ApiResultStatusCode.NotFound); throw new AppException("Setting not found", ApiResultStatusCode.NotFound);
var baseSetting = await martenRepositoryWrapper.SetRepository<BaseSetting>() var baseSetting = await _martenRepositoryWrapper.SetRepository<BaseSetting>()
.GetEntityAsync(s => s.Name == settingName, cancellationToken); .GetEntityAsync(s => s.Name == settingName, cancellationToken);
object? setting; object? setting;
if (baseSetting == null) if (baseSetting == null)
@ -29,7 +34,7 @@ public class SettingService(IMartenRepositoryWrapper martenRepositoryWrapper) :
if (type == null) if (type == null)
throw new AppException("Setting not found", ApiResultStatusCode.NotFound); throw new AppException("Setting not found", ApiResultStatusCode.NotFound);
var baseSetting = await martenRepositoryWrapper.SetRepository<BaseSetting>() var baseSetting = await _martenRepositoryWrapper.SetRepository<BaseSetting>()
.GetEntityAsync(s => s.Name == settingName, cancellationToken); .GetEntityAsync(s => s.Name == settingName, cancellationToken);
if (baseSetting == null) if (baseSetting == null)
@ -46,7 +51,7 @@ public class SettingService(IMartenRepositoryWrapper martenRepositoryWrapper) :
baseSetting.JsonData = JsonConvert.SerializeObject(settingObj.Deserialize(type)); baseSetting.JsonData = JsonConvert.SerializeObject(settingObj.Deserialize(type));
} }
await martenRepositoryWrapper.SetRepository<BaseSetting>() await _martenRepositoryWrapper.SetRepository<BaseSetting>()
.AddOrUpdateEntityAsync(baseSetting, cancellationToken); .AddOrUpdateEntityAsync(baseSetting, cancellationToken);
} }
} }

View File

@ -1,5 +1,4 @@
using System.IO.Compression; using System.IO.Compression;
using System.Net;
using System.Xml; using System.Xml;
using Netina.Core.Models; using Netina.Core.Models;
using Netina.Domain.Entities.ProductCategories; using Netina.Domain.Entities.ProductCategories;
@ -7,14 +6,23 @@ using Netina.Domain.Entities.ProductCategories;
namespace Netina.Core.BaseServices; namespace Netina.Core.BaseServices;
public class SiteMapService( public class SiteMapService : ISiteMapService
IOptionsSnapshot<SiteSettings> snapshot, {
private readonly IUploadFileService _uploadFileService;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IPageService _pageService;
private readonly SiteSettings _siteSetting;
public SiteMapService(IOptionsSnapshot<SiteSettings> snapshot,
IUploadFileService uploadFileService, IUploadFileService uploadFileService,
IRepositoryWrapper repositoryWrapper, IRepositoryWrapper repositoryWrapper,
IPageService pageService) : ISiteMapService IPageService pageService)
{ {
private readonly SiteSettings _siteSetting = snapshot.Value; _uploadFileService = uploadFileService;
_repositoryWrapper = repositoryWrapper;
_pageService = pageService;
_siteSetting = snapshot.Value;
}
public async Task CreateSiteMapAsync() public async Task CreateSiteMapAsync()
{ {
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
@ -30,11 +38,11 @@ public class SiteMapService(
doc.AppendChild(root); doc.AppendChild(root);
var productCategories = await repositoryWrapper.SetRepository<ProductCategory>() var productCategories = await _repositoryWrapper.SetRepository<ProductCategory>()
.TableNoTracking .TableNoTracking
.ToListAsync(); .ToListAsync();
var blogCategories= await repositoryWrapper.SetRepository<BlogCategory>() var blogCategories= await _repositoryWrapper.SetRepository<BlogCategory>()
.TableNoTracking .TableNoTracking
.ToListAsync(); .ToListAsync();
@ -88,7 +96,7 @@ public class SiteMapService(
doc.WriteTo(writer); doc.WriteTo(writer);
writer.Flush(); writer.Flush();
byte[] byteArray = stream.ToArray(); byte[] byteArray = stream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = byteArray, FileBytes = byteArray,
ContentType = "text/xml", ContentType = "text/xml",
@ -99,7 +107,7 @@ public class SiteMapService(
await CreateCategoriesSiteMapsAsync(); await CreateCategoriesSiteMapsAsync();
await CreateProductsSiteMapsAsync(); await CreateProductsSiteMapsAsync();
await CreateBlogsSiteMapsAsync(); await CreateBlogsSiteMapsAsync();
await CreateBrandsSiteMapsAsync(); //await CreateBrandsSiteMapsAsync();
await CreateBlogCategoriesSiteMapsAsync(); await CreateBlogCategoriesSiteMapsAsync();
await CreatePagesSiteMapsAsync(); await CreatePagesSiteMapsAsync();
@ -110,7 +118,7 @@ public class SiteMapService(
{ {
var siteMapsUId = SiteMapUIds.Pages; var siteMapsUId = SiteMapUIds.Pages;
var pages = await pageService.GetPagesAsync(); var pages = await _pageService.GetPagesAsync();
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null); XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null);
@ -123,12 +131,9 @@ public class SiteMapService(
root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1"); root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1");
doc.AppendChild(root); doc.AppendChild(root);
foreach (var page in pages.Where(p=>p.Indexing)) foreach (var page in pages)
{ {
string slugHtml = page.Slug; var productUrl = $"{_siteSetting.WebSiteUrl}/{page.Slug}";
if (slugHtml.Contains(' '))
slugHtml = WebUtility.UrlEncode(slugHtml.Replace(' ', '-'));
var productUrl = $"{_siteSetting.WebSiteUrl}/{slugHtml}";
XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI);
root.AppendChild(urlElement); root.AppendChild(urlElement);
@ -165,7 +170,7 @@ public class SiteMapService(
zipStream.Close(); zipStream.Close();
var siteMapArray = compressedStream.ToArray(); var siteMapArray = compressedStream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = siteMapArray, FileBytes = siteMapArray,
ContentType = "text/plain", ContentType = "text/plain",
@ -179,7 +184,7 @@ public class SiteMapService(
{ {
var siteMapsUId = SiteMapUIds.Brands; var siteMapsUId = SiteMapUIds.Brands;
var brands = await repositoryWrapper.SetRepository<Brand>() var brands = await _repositoryWrapper.SetRepository<Brand>()
.TableNoTracking .TableNoTracking
.ToListAsync(); .ToListAsync();
@ -196,10 +201,7 @@ public class SiteMapService(
foreach (var brand in brands) foreach (var brand in brands)
{ {
string slugHtml = brand.Slug; var productUrl = $"{_siteSetting.WebSiteUrl}/brands/{brand.Id}/{brand.Slug}";
if (slugHtml.Contains(' '))
slugHtml = WebUtility.UrlEncode(slugHtml.Replace(' ', '-'));
var productUrl = $"{_siteSetting.WebSiteUrl}/brands/{brand.Id}/{slugHtml}";
XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI);
root.AppendChild(urlElement); root.AppendChild(urlElement);
@ -236,7 +238,7 @@ public class SiteMapService(
zipStream.Close(); zipStream.Close();
var siteMapArray = compressedStream.ToArray(); var siteMapArray = compressedStream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = siteMapArray, FileBytes = siteMapArray,
ContentType = "text/plain", ContentType = "text/plain",
@ -251,7 +253,7 @@ public class SiteMapService(
{ {
var siteMapsUId = SiteMapUIds.Categories; var siteMapsUId = SiteMapUIds.Categories;
var categories = await repositoryWrapper.SetRepository<ProductCategory>() var categories = await _repositoryWrapper.SetRepository<ProductCategory>()
.TableNoTracking .TableNoTracking
.ToListAsync(); .ToListAsync();
@ -268,10 +270,7 @@ public class SiteMapService(
foreach (var productCategory in categories) foreach (var productCategory in categories)
{ {
string slugHtml = productCategory.Slug; var productUrl = $"{_siteSetting.WebSiteUrl}/categories/{productCategory.Id}/{productCategory.Slug}";
if (slugHtml.Contains(' '))
slugHtml = WebUtility.UrlEncode(slugHtml.Replace(' ', '-'));
var productUrl = $"{_siteSetting.WebSiteUrl}/categories/{productCategory.Id}/{slugHtml}";
XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI);
root.AppendChild(urlElement); root.AppendChild(urlElement);
@ -308,7 +307,7 @@ public class SiteMapService(
zipStream.Close(); zipStream.Close();
var siteMapArray = compressedStream.ToArray(); var siteMapArray = compressedStream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = siteMapArray, FileBytes = siteMapArray,
ContentType = "text/plain", ContentType = "text/plain",
@ -322,9 +321,8 @@ public class SiteMapService(
private async Task CreateProductsSiteMapsAsync() private async Task CreateProductsSiteMapsAsync()
{ {
var products = await repositoryWrapper.SetRepository<Product>() var products = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.Where(p=>!p.IsSubProduct)
.Select(ProductMapper.ProjectToSDto) .Select(ProductMapper.ProjectToSDto)
.ToListAsync(); .ToListAsync();
@ -345,10 +343,8 @@ public class SiteMapService(
foreach (var product in group) foreach (var product in group)
{ {
string slugHtml = product.Slug;
if (slugHtml.Contains(' ')) var productUrl = $"{_siteSetting.WebSiteUrl}/products/{product.Id}/{product.Slug}";
slugHtml = WebUtility.UrlEncode(slugHtml.Replace(' ', '-'));
var productUrl = $"{_siteSetting.WebSiteUrl}/products/{product.Id}/{slugHtml}";
XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI); XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI);
root.AppendChild(urlElement); root.AppendChild(urlElement);
@ -404,7 +400,7 @@ public class SiteMapService(
zipStream.Close(); zipStream.Close();
var siteMapArray = compressedStream.ToArray(); var siteMapArray = compressedStream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = siteMapArray, FileBytes = siteMapArray,
ContentType = "text/plain", ContentType = "text/plain",
@ -421,7 +417,7 @@ public class SiteMapService(
private async Task CreateBlogsSiteMapsAsync() private async Task CreateBlogsSiteMapsAsync()
{ {
var blogs = await repositoryWrapper.SetRepository<Blog>() var blogs = await _repositoryWrapper.SetRepository<Blog>()
.TableNoTracking .TableNoTracking
.Select(BlogMapper.ProjectToSDto) .Select(BlogMapper.ProjectToSDto)
.ToListAsync(); .ToListAsync();
@ -448,11 +444,7 @@ public class SiteMapService(
root.AppendChild(urlElement); root.AppendChild(urlElement);
XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI); XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI);
loc.InnerText = Path.Combine($"{_siteSetting.WebSiteUrl}/blogs/{blog.Id}/{blog.Slug}");
string slugHtml = blog.Slug;
if (slugHtml.Contains(' '))
slugHtml = WebUtility.UrlEncode(slugHtml.Replace(' ', '-'));
loc.InnerText = Path.Combine($"{_siteSetting.WebSiteUrl}/blogs/{blog.Id}/{slugHtml}");
urlElement.AppendChild(loc); urlElement.AppendChild(loc);
XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI); XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI);
@ -538,7 +530,7 @@ public class SiteMapService(
zipStream.Close(); zipStream.Close();
var siteMapArray = compressedStream.ToArray(); var siteMapArray = compressedStream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = siteMapArray, FileBytes = siteMapArray,
ContentType = "text/plain", ContentType = "text/plain",
@ -556,7 +548,7 @@ public class SiteMapService(
{ {
var siteMapsUId = SiteMapUIds.BlogCategories; var siteMapsUId = SiteMapUIds.BlogCategories;
var blogCategories = await repositoryWrapper.SetRepository<BlogCategory>() var blogCategories = await _repositoryWrapper.SetRepository<BlogCategory>()
.TableNoTracking .TableNoTracking
.ToListAsync(); .ToListAsync();
@ -610,7 +602,7 @@ public class SiteMapService(
zipStream.Close(); zipStream.Close();
var siteMapArray = compressedStream.ToArray(); var siteMapArray = compressedStream.ToArray();
await uploadFileService.UploadFileByteAsync(new FileUploadRequest await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{ {
FileBytes = siteMapArray, FileBytes = siteMapArray,
ContentType = "text/plain", ContentType = "text/plain",

View File

@ -8,7 +8,6 @@ public static class CoreConfig
public static async Task CoreInit(this IApplicationBuilder app) public static async Task CoreInit(this IApplicationBuilder app)
{ {
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("NjA1NkAzMjM2MkUzMTJFMzliSzVTQlJKN0NLVzNVOFVKSlErcVEzYW9PSkZ2dUhicHliVjkrMncxdHpRPQ==");
var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>(); var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope()) using (var scope = scopeFactory.CreateScope())
{ {

View File

@ -1,17 +1,21 @@
namespace Netina.Core.CoreServices.SearchServices; namespace Netina.Core.CoreServices.SearchServices;
public class GetEmallsProductsQueryHandler( public class GetEmallsProductsQueryHandler : IRequestHandler<GetEmallsProductsQuery, EmallsResponseDto>
IRepositoryWrapper repositoryWrapper,
IMediator mediator,
IOptionsSnapshot<SiteSettings> optionsSnapshot)
: IRequestHandler<GetEmallsProductsQuery, EmallsResponseDto>
{ {
private readonly SiteSettings _siteSetting = optionsSnapshot.Value; private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
private readonly SiteSettings _siteSetting;
public GetEmallsProductsQueryHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator, IOptionsSnapshot<SiteSettings> optionsSnapshot)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
_siteSetting = optionsSnapshot.Value;
}
public async Task<EmallsResponseDto> Handle(GetEmallsProductsQuery request, CancellationToken cancellationToken) public async Task<EmallsResponseDto> Handle(GetEmallsProductsQuery request, CancellationToken cancellationToken)
{ {
var page = request.Page; var page = request.Page;
var productsSDto = await repositoryWrapper.SetRepository<Product>() var productsSDto = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.OrderByDescending(p => p.ModifiedAt == DateTime.MinValue ? p.CreatedAt : p.ModifiedAt) .OrderByDescending(p => p.ModifiedAt == DateTime.MinValue ? p.CreatedAt : p.ModifiedAt)
.Select(p => new ProductSDto .Select(p => new ProductSDto
@ -33,7 +37,7 @@ public class GetEmallsProductsQueryHandler(
foreach (var productSDto in productsSDto) foreach (var productSDto in productsSDto)
await mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken); await _mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
var products = new List<EmallsProductResponseDto>(); var products = new List<EmallsProductResponseDto>();
foreach (var product in productsSDto) foreach (var product in productsSDto)
{ {
@ -47,18 +51,18 @@ public class GetEmallsProductsQueryHandler(
}; };
if (product.Cost > product.CostWithDiscount) if (product.Cost > product.CostWithDiscount)
{ {
torobProduct.old_price = (int)product.Cost / 10; torobProduct.old_price = (int)product.Cost;
torobProduct.price = (int)product.CostWithDiscount / 10; torobProduct.price = (int)product.CostWithDiscount;
} }
else else
torobProduct.price = (int)product.Cost / 10; torobProduct.price = (int)product.Cost;
products.Add(torobProduct); products.Add(torobProduct);
} }
var response = new EmallsResponseDto(); var response = new EmallsResponseDto();
response.item_per_page = request.Count; response.item_per_page = request.Count;
response.page_num = request.Page; response.page_num = request.Page;
response.total_items = (await repositoryWrapper.SetRepository<Product>().TableNoTracking.CountAsync(cancellationToken)); response.total_items = (await _repositoryWrapper.SetRepository<Product>().TableNoTracking.CountAsync(cancellationToken));
response.pages_count = response.total_items / request.Count; response.pages_count = response.total_items / request.Count;
response.products = products; response.products = products;

View File

@ -2,22 +2,27 @@
namespace Netina.Core.CoreServices.SearchServices; namespace Netina.Core.CoreServices.SearchServices;
public class GetThumbSearchProductsQueryHandler(IRepositoryWrapper repositoryWrapper) public class GetThumbSearchProductsQueryHandler : IRequestHandler<GetThumbSearchProductsQuery, SearchResponseDto>
: IRequestHandler<GetThumbSearchProductsQuery, SearchResponseDto>
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
public GetThumbSearchProductsQueryHandler(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
public async Task<SearchResponseDto> Handle(GetThumbSearchProductsQuery request, CancellationToken cancellationToken) public async Task<SearchResponseDto> Handle(GetThumbSearchProductsQuery request, CancellationToken cancellationToken)
{ {
var searchQuery = request.Name; var searchQuery = request.Name;
var products = await repositoryWrapper.SetRepository<Product>() var products = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.OrderByDescending(p => EF.Functions.TrigramsSimilarity(p.PersianName, searchQuery)) .OrderByDescending(p => EF.Functions.TrigramsSimilarity(p.PersianName, searchQuery))
.Take(8) .Take(8)
.Select(ProductMapper.ProjectToSDto) .Select(ProductMapper.ProjectToSDto)
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);
var categories = await repositoryWrapper.SetRepository<ProductCategory>() var categories = await _repositoryWrapper.SetRepository<ProductCategory>()
.TableNoTracking .TableNoTracking
.OrderByDescending(p => EF.Functions.TrigramsSimilarity(p.Name.ToLower().Trim(), searchQuery)) .OrderByDescending(p => EF.Functions.TrigramsSimilarity(p.Name.ToLower().Trim(), searchQuery))
.Take(8) .Take(8)

View File

@ -1,17 +1,21 @@
namespace Netina.Core.CoreServices.SearchServices; namespace Netina.Core.CoreServices.SearchServices;
public class GetTorobProductsQueryHandler( public class GetTorobProductsQueryHandler : IRequestHandler<GetTorobProductsQuery, List<TorobProductResponseDto>>
IRepositoryWrapper repositoryWrapper,
IMediator mediator,
IOptionsSnapshot<SiteSettings> optionsSnapshot)
: IRequestHandler<GetTorobProductsQuery, List<TorobProductResponseDto>>
{ {
private readonly SiteSettings _siteSetting = optionsSnapshot.Value; private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
private readonly SiteSettings _siteSetting;
public GetTorobProductsQueryHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator, IOptionsSnapshot<SiteSettings> optionsSnapshot)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
_siteSetting = optionsSnapshot.Value;
}
public async Task<List<TorobProductResponseDto>> Handle(GetTorobProductsQuery request, CancellationToken cancellationToken) public async Task<List<TorobProductResponseDto>> Handle(GetTorobProductsQuery request, CancellationToken cancellationToken)
{ {
int page = request.Page == 0 ? 1 : request.Page; int page = request.Page == 0 ? 1 : request.Page;
var productsSDto = await repositoryWrapper.SetRepository<Product>() var productsSDto = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.OrderByDescending(p => p.ModifiedAt == DateTime.MinValue ? p.CreatedAt : p.ModifiedAt) .OrderByDescending(p => p.ModifiedAt == DateTime.MinValue ? p.CreatedAt : p.ModifiedAt)
.Select(p => new ProductSDto .Select(p => new ProductSDto
@ -33,7 +37,7 @@ public class GetTorobProductsQueryHandler(
foreach (var productSDto in productsSDto) foreach (var productSDto in productsSDto)
await mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken); await _mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
var products = new List<TorobProductResponseDto>(); var products = new List<TorobProductResponseDto>();
foreach (var product in productsSDto) foreach (var product in productsSDto)
{ {
@ -45,11 +49,11 @@ public class GetTorobProductsQueryHandler(
}; };
if (product.Cost > product.CostWithDiscount) if (product.Cost > product.CostWithDiscount)
{ {
torobProduct.old_price = product.Cost / 10; torobProduct.old_price = product.Cost;
torobProduct.price = product.CostWithDiscount / 10; torobProduct.price = product.CostWithDiscount;
} }
else else
torobProduct.price = product.Cost / 10; torobProduct.price = product.Cost;
products.Add(torobProduct); products.Add(torobProduct);
} }

View File

@ -2,17 +2,22 @@
namespace Netina.Core.CoreServices.WebSiteServices; namespace Netina.Core.CoreServices.WebSiteServices;
public class GetWebSiteNavBarCommandHandler( public class GetWebSiteNavBarCommandHandler : IRequestHandler<GetWebSiteNavBarCommand , List<NavMenuItem>>
IRepositoryWrapper repositoryWrapper,
ISettingService settingService,
IOptionsSnapshot<SiteSettings> optionsSnapshot)
: IRequestHandler<GetWebSiteNavBarCommand, List<NavMenuItem>>
{ {
private readonly SiteSettings _siteSetting = optionsSnapshot.Value; private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ISettingService _settingService;
private readonly SiteSettings _siteSetting;
public GetWebSiteNavBarCommandHandler(IRepositoryWrapper repositoryWrapper , ISettingService settingService,IOptionsSnapshot<SiteSettings> optionsSnapshot)
{
_repositoryWrapper = repositoryWrapper;
_settingService = settingService;
_siteSetting = optionsSnapshot.Value;
}
public async Task<List<NavMenuItem>> Handle(GetWebSiteNavBarCommand request, CancellationToken cancellationToken) public async Task<List<NavMenuItem>> Handle(GetWebSiteNavBarCommand request, CancellationToken cancellationToken)
{ {
var navBarSetting = await settingService.GetSettingAsync(nameof(NavMenuSetting), cancellationToken) as NavMenuSetting; var navBarSetting = await _settingService.GetSettingAsync(nameof(NavMenuSetting), cancellationToken) as NavMenuSetting;
var navBarItems = new List<NavMenuItem>(); var navBarItems = new List<NavMenuItem>();
if (navBarSetting == null) if (navBarSetting == null)
return new List<NavMenuItem>(); return new List<NavMenuItem>();
@ -25,7 +30,7 @@ public class GetWebSiteNavBarCommandHandler(
if (navBarSetting.ShowBlogCategories) if (navBarSetting.ShowBlogCategories)
{ {
var baseCategories = await repositoryWrapper.SetRepository<BlogCategory>() var baseCategories = await _repositoryWrapper.SetRepository<BlogCategory>()
.TableNoTracking .TableNoTracking
.OrderByDescending(c => c.CreatedAt) .OrderByDescending(c => c.CreatedAt)
.Select(BlogCategoryMapper.ProjectToSDto) .Select(BlogCategoryMapper.ProjectToSDto)
@ -49,7 +54,7 @@ public class GetWebSiteNavBarCommandHandler(
} }
else if (navBarSetting.ShowProductCategories) else if (navBarSetting.ShowProductCategories)
{ {
var baseCategories = await repositoryWrapper.SetRepository<ProductCategory>() var baseCategories = await _repositoryWrapper.SetRepository<ProductCategory>()
.TableNoTracking .TableNoTracking
.OrderByDescending(c => c.CreatedAt) .OrderByDescending(c => c.CreatedAt)
.Select(ProductCategoryMapper.ProjectToSDto) .Select(ProductCategoryMapper.ProjectToSDto)

View File

@ -1,36 +0,0 @@
using Netina.Domain.Entities.Comments;
namespace Netina.Core.EntityServices.CommentHandlers;
public class ConfirmCommentCommandHandler(IRepositoryWrapper repositoryWrapper)
: IRequestHandler<ConfirmCommentCommand, Guid>
{
public async Task<Guid> Handle(ConfirmCommentCommand request, CancellationToken cancellationToken)
{
var review = await repositoryWrapper.SetRepository<Comment>().TableNoTracking
.FirstOrDefaultAsync(r => r.Id == request.Id, cancellationToken);
if (review == null)
throw new AppException("Comment not found", ApiResultStatusCode.NotFound);
review.ConfirmReview();
var productComment = await repositoryWrapper.SetRepository<ProductComment>()
.TableNoTracking.FirstOrDefaultAsync(f => f.Id == request.Id, cancellationToken);
if (productComment != null)
{
var product = await repositoryWrapper.SetRepository<Product>()
.TableNoTracking
.FirstOrDefaultAsync(p => p.Id == productComment.ProductId, cancellationToken);
if (product == null)
throw new AppException("Product not found", ApiResultStatusCode.NotFound);
product.AddRate(productComment.Rate);
repositoryWrapper.SetRepository<Product>().Update(product);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
}
repositoryWrapper.SetRepository<Comment>().Update(review);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
return review.Id;
}
}

View File

@ -1,37 +1,43 @@
using Netina.Domain.Entities.ProductCategories; namespace Netina.Core.EntityServices.DiscountHandlers;
namespace Netina.Core.EntityServices.DiscountHandlers; public class CalculateOrderDiscountCommandHandler : IRequestHandler<CalculateOrderDiscountCommand , double>
public class CalculateOrderDiscountCommandHandler(
IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService)
: IRequestHandler<CalculateOrderDiscountCommand, double>
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
public CalculateOrderDiscountCommandHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService)
{
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
}
public async Task<double> Handle(CalculateOrderDiscountCommand request, CancellationToken cancellationToken) public async Task<double> Handle(CalculateOrderDiscountCommand request, CancellationToken cancellationToken)
{ {
if (request.Order == null) if (request.Order == null)
throw new AppException("Order is null", ApiResultStatusCode.BadRequest); throw new AppException("Order is null", ApiResultStatusCode.BadRequest);
var discount = await repositoryWrapper.SetRepository<Discount>() var discount = await _repositoryWrapper.SetRepository<Discount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
if (discount == null) if (discount == null)
throw new AppException("تخفیف وجود منقضی شده است یا وجود ندارد", ApiResultStatusCode.NotFound); throw new AppException("تخفیف وجود منقضی شده است یا وجود ندارد", ApiResultStatusCode.NotFound);
if (_currentUserService.UserId != null && Guid.TryParse(_currentUserService.UserId, out Guid userId))
{
var discountedUserOrder = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.FirstOrDefaultAsync(f => f.CustomerId == userId && f.DiscountCode == discount.Code, cancellationToken);
if (discountedUserOrder != null)
throw new AppException("شما یک بار از این کد تخفیف استفاده کرده اید", ApiResultStatusCode.BadRequest);
}
if (discount.IsForFirstPurchase) if (discount.IsForFirstPurchase)
{ {
if (currentUserService.UserId != null && Guid.TryParse(currentUserService.UserId, out Guid firstPurchaseUserId)) if (_currentUserService.UserId != null && Guid.TryParse(_currentUserService.UserId, out Guid firstPurchaseUserId))
{ {
var customer = await repositoryWrapper.SetRepository<Customer>() var userOrderCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == firstPurchaseUserId, cancellationToken); .CountAsync(f => f.CustomerId == firstPurchaseUserId && f.DiscountCode == discount.Code, cancellationToken);
if (customer == null)
throw new BaseApiException(ApiResultStatusCode.NotFound, "Customer not found");
var userOrderCount = await repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.CountAsync(f => f.CustomerId == customer.Id && f.DiscountCode == discount.Code, cancellationToken);
if (userOrderCount > 0) if (userOrderCount > 0)
throw new AppException("شما قبلا خریدی داشته اید و نمیتوانید از تخفیف اولین خرید استفاده کنید", ApiResultStatusCode.BadRequest); throw new AppException("شما قبلا خریدی داشته اید و نمیتوانید از تخفیف اولین خرید استفاده کنید", ApiResultStatusCode.BadRequest);
} }
@ -48,22 +54,18 @@ public class CalculateOrderDiscountCommandHandler(
} }
else if (discount.Type == DiscountType.Category) else if (discount.Type == DiscountType.Category)
{ {
var categoryDiscount = await repositoryWrapper.SetRepository<CategoryDiscount>() var categoryDiscount = await _repositoryWrapper.SetRepository<CategoryDiscount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
if ( categoryDiscount!=null && !categoryDiscount.IsExpired()) if ( categoryDiscount!=null && !categoryDiscount.IsExpired())
{ {
var subCats = await repositoryWrapper.SetRepository<ProductCategory>().TableNoTracking totalPrice = request.Order.OrderProducts.Where(op => op.ProductCategoryId == categoryDiscount.CategoryId).Sum(op => op.ProductCost);
.Where(c => c.ParentId == categoryDiscount.CategoryId)
.Select(c => c.Id)
.ToListAsync(cancellationToken);
subCats.Add(categoryDiscount.CategoryId);
totalPrice = request.Order.OrderProducts.Where(op => subCats.Contains(op.ProductCategoryId)).Sum(op => op.ProductCost);
} }
} }
else if (discount.Type == DiscountType.Product) else if (discount.Type == DiscountType.Product)
{ {
var productDiscount = await repositoryWrapper.SetRepository<ProductDiscount>() var productDiscount = await _repositoryWrapper.SetRepository<ProductDiscount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
@ -73,18 +75,6 @@ public class CalculateOrderDiscountCommandHandler(
} }
} }
else if (discount.Type == DiscountType.Brand)
{
var brandDiscount = await repositoryWrapper.SetRepository<BrandDiscount>()
.TableNoTracking
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
if (brandDiscount != null && !brandDiscount.IsExpired())
{
totalPrice = request.Order.OrderProducts.Where(op => op.BrandId == brandDiscount.BrandId).Sum(op => op.ProductCost);
}
}
else if (discount.Type == DiscountType.Subscriber) else if (discount.Type == DiscountType.Subscriber)
{ {
throw new NotImplementedException("Subscribe discount not implemented"); throw new NotImplementedException("Subscribe discount not implemented");

View File

@ -1,8 +1,15 @@
namespace Netina.Core.EntityServices.DiscountHandlers; namespace Netina.Core.EntityServices.DiscountHandlers;
public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositoryWrapper) public class CalculateProductDiscountCommandHandler : IRequestHandler<CalculateProductDiscountCommand, bool>
: IRequestHandler<CalculateProductDiscountCommand, bool>
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
public CalculateProductDiscountCommandHandler(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
public async Task<bool> Handle(CalculateProductDiscountCommand request, CancellationToken cancellationToken) public async Task<bool> Handle(CalculateProductDiscountCommand request, CancellationToken cancellationToken)
{ {
if (request.Product is ProductSDto product) if (request.Product is ProductSDto product)
@ -23,7 +30,7 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.CostWithDiscount = request.Cost; request.CostWithDiscount = request.Cost;
double totalPrice = request.Cost; double totalPrice = request.Cost;
var allDiscount = await repositoryWrapper.SetRepository<Discount>() var allDiscount = await _repositoryWrapper.SetRepository<Discount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.Type == DiscountType.All && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken); .FirstOrDefaultAsync(d => d.Type == DiscountType.All && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken);
@ -35,7 +42,7 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.HasDiscount = true; request.HasDiscount = true;
} }
var categoryDiscount = await repositoryWrapper.SetRepository<CategoryDiscount>() var categoryDiscount = await _repositoryWrapper.SetRepository<CategoryDiscount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.CategoryId == request.CategoryId && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken); .FirstOrDefaultAsync(d => d.CategoryId == request.CategoryId && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken);
@ -46,7 +53,7 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.HasDiscount = true; request.HasDiscount = true;
} }
var productDiscount = await repositoryWrapper.SetRepository<ProductDiscount>() var productDiscount = await _repositoryWrapper.SetRepository<ProductDiscount>()
.TableNoTracking .TableNoTracking
.Where(d => d.HasCode == false && d.ProductId == request.Id && d.ExpireDate.Date >= DateTime.Today.Date) .Where(d => d.HasCode == false && d.ProductId == request.Id && d.ExpireDate.Date >= DateTime.Today.Date)
.OrderByDescending(d => d.CreatedAt) .OrderByDescending(d => d.CreatedAt)
@ -68,12 +75,6 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.DiscountPercent = request.Cost == 0 ? 0 : 100 - 100 * request.CostWithDiscount / request.Cost; request.DiscountPercent = request.Cost == 0 ? 0 : 100 - 100 * request.CostWithDiscount / request.Cost;
} }
if (request.DiscountPercent == 0)
{
request.CostWithDiscount = request.Cost;
request.HasDiscount = false;
}
return request; return request;
} }
@ -84,7 +85,7 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.CostWithDiscount = request.Cost; request.CostWithDiscount = request.Cost;
double totalPrice = request.Cost; double totalPrice = request.Cost;
var allDiscount = await repositoryWrapper.SetRepository<Discount>() var allDiscount = await _repositoryWrapper.SetRepository<Discount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.Type == DiscountType.All && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken); .FirstOrDefaultAsync(d => d.Type == DiscountType.All && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken);
@ -96,7 +97,7 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.HasDiscount = true; request.HasDiscount = true;
} }
var categoryDiscount = await repositoryWrapper.SetRepository<CategoryDiscount>() var categoryDiscount = await _repositoryWrapper.SetRepository<CategoryDiscount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.CategoryId == request.CategoryId && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken); .FirstOrDefaultAsync(d => d.CategoryId == request.CategoryId && d.HasCode == false && d.ExpireDate.Date >= DateTime.Today.Date, cancellationToken);
@ -107,7 +108,7 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.HasDiscount = true; request.HasDiscount = true;
} }
var productDiscount = await repositoryWrapper.SetRepository<ProductDiscount>() var productDiscount = await _repositoryWrapper.SetRepository<ProductDiscount>()
.TableNoTracking .TableNoTracking
.Where(d => d.HasCode == false && d.ProductId == request.Id && d.ExpireDate.Date >= DateTime.Today.Date) .Where(d => d.HasCode == false && d.ProductId == request.Id && d.ExpireDate.Date >= DateTime.Today.Date)
.OrderByDescending(d => d.CreatedAt) .OrderByDescending(d => d.CreatedAt)
@ -131,12 +132,6 @@ public class CalculateProductDiscountCommandHandler(IRepositoryWrapper repositor
request.CostWithDiscount = discountPrice; request.CostWithDiscount = discountPrice;
request.DiscountPercent = request.Cost == 0 ? 0 : 100 - 100 * request.CostWithDiscount / request.Cost; request.DiscountPercent = request.Cost == 0 ? 0 : 100 - 100 * request.CostWithDiscount / request.Cost;
} }
if (request.DiscountPercent == 0)
{
request.CostWithDiscount = request.Cost;
request.HasDiscount = false;
}
return request; return request;
} }

View File

@ -1,30 +0,0 @@
namespace Netina.Core.EntityServices.DiscountHandlers;
public class CheckUserDiscountFirstUseCommandHandler(
IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService)
: IRequestHandler<CheckUserDiscountFirstUseCommand, bool>
{
public async Task<bool> Handle(CheckUserDiscountFirstUseCommand request, CancellationToken cancellationToken)
{
if (currentUserService.UserId != null && Guid.TryParse(currentUserService.UserId, out Guid userId))
{
var customer = await repositoryWrapper.SetRepository<Customer>()
.TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken);
if (customer == null)
throw new BaseApiException(ApiResultStatusCode.NotFound, "Customer not found");
var discountedUserOrder = await repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.FirstOrDefaultAsync(f => f.CustomerId == customer.Id && f.DiscountCode == request.DiscountCode,
cancellationToken);
if (discountedUserOrder != null)
return false;
return true;
}
else
throw new BaseApiException(ApiResultStatusCode.BadRequest,"UserId is wrong");
}
}

View File

@ -1,38 +1,48 @@
namespace Netina.Core.EntityServices.MarketerHandlers; namespace Netina.Core.EntityServices.MarketerHandlers;
public class CreateMarketerDiscountCommandHandler( public class CreateMarketerDiscountCommandHandler : IRequestHandler<CreateMarketerDiscountCommand, string>
UserManager<ApplicationUser> userManager, {
private readonly UserManager<ApplicationUser> _userManager;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
private readonly ISettingService _settingService;
public CreateMarketerDiscountCommandHandler(UserManager<ApplicationUser> userManager,
IRepositoryWrapper repositoryWrapper, IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService, ICurrentUserService currentUserService,
ISettingService settingService) ISettingService settingService)
: IRequestHandler<CreateMarketerDiscountCommand, string>
{ {
_userManager = userManager;
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
_settingService = settingService;
}
public async Task<string> Handle(CreateMarketerDiscountCommand request, CancellationToken cancellationToken) public async Task<string> Handle(CreateMarketerDiscountCommand request, CancellationToken cancellationToken)
{ {
var userId = request.MarketerUserId; var userId = request.MarketerUserId;
if (userId == default) if (userId == default)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("User id is null"); throw new AppException("User id is null");
if (!Guid.TryParse(currentUserService.UserId, out userId)) if (!Guid.TryParse(_currentUserService.UserId, out userId))
throw new AppException("User id is wrong"); throw new AppException("User id is wrong");
} }
var user = await userManager.FindByIdAsync(userId.ToString()); var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null) if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
var marketer = await repositoryWrapper.SetRepository<Marketer>() var marketer = await _repositoryWrapper.SetRepository<Marketer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(m => m.UserId == user.Id, cancellationToken); .FirstOrDefaultAsync(m => m.UserId == user.Id, cancellationToken);
if (marketer == null) if (marketer == null)
throw new AppException("Marketer not found", ApiResultStatusCode.NotFound); throw new AppException("Marketer not found", ApiResultStatusCode.NotFound);
var foundedDiscount = await repositoryWrapper.SetRepository<Discount>() var foundedDiscount = await _repositoryWrapper.SetRepository<Discount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.IsForSaleCooperation && d.MarketerId == marketer.Id, cancellationToken); .FirstOrDefaultAsync(d => d.IsForSaleCooperation && d.MarketerId == marketer.Id, cancellationToken);
if (foundedDiscount == null) if (foundedDiscount == null)
{ {
var setting = await settingService.GetSettingAsync(nameof(MarketerSetting), cancellationToken); var setting = await _settingService.GetSettingAsync(nameof(MarketerSetting), cancellationToken);
int discountPercent = 10; int discountPercent = 10;
if (setting is MarketerSetting marketerSetting) if (setting is MarketerSetting marketerSetting)
discountPercent = marketerSetting.DiscountPercent; discountPercent = marketerSetting.DiscountPercent;
@ -43,8 +53,8 @@ public class CreateMarketerDiscountCommandHandler(
false, 0, false, true, 0, false, false, false); false, 0, false, true, 0, false, false, false);
foundedDiscount.SetCorporate(marketer.Id); foundedDiscount.SetCorporate(marketer.Id);
repositoryWrapper.SetRepository<Discount>().Add(foundedDiscount); _repositoryWrapper.SetRepository<Discount>().Add(foundedDiscount);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
return foundedDiscount.Code; return foundedDiscount.Code;
} }

View File

@ -2,12 +2,18 @@
namespace Netina.Core.EntityServices.MarketerHandlers; namespace Netina.Core.EntityServices.MarketerHandlers;
public class GetMarketerProfileQueryHandler( public class GetMarketerProfileQueryHandler : IRequestHandler<GetMarketerProfileQuery, MarketerProfileResponseDto>
IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService,
ISettingService settingService)
: IRequestHandler<GetMarketerProfileQuery, MarketerProfileResponseDto>
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
private readonly ISettingService _settingService;
public GetMarketerProfileQueryHandler(IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService,ISettingService settingService)
{
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
_settingService = settingService;
}
public async Task<MarketerProfileResponseDto> Handle(GetMarketerProfileQuery request, CancellationToken cancellationToken) public async Task<MarketerProfileResponseDto> Handle(GetMarketerProfileQuery request, CancellationToken cancellationToken)
{ {
Guid marketerId; Guid marketerId;
@ -15,17 +21,17 @@ public class GetMarketerProfileQueryHandler(
if (request.MarketerId != null) if (request.MarketerId != null)
{ {
marketerId = request.MarketerId.Value; marketerId = request.MarketerId.Value;
marketer = await repositoryWrapper.SetRepository<Marketer>() marketer = await _repositoryWrapper.SetRepository<Marketer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(m => m.Id == marketerId, cancellationToken); .FirstOrDefaultAsync(m => m.Id == marketerId, cancellationToken);
} }
else else
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new BaseApiException("User id is null"); throw new BaseApiException("User id is null");
if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new BaseApiException("User id is wrong"); throw new BaseApiException("User id is wrong");
marketer = await repositoryWrapper.SetRepository<Marketer>() marketer = await _repositoryWrapper.SetRepository<Marketer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken); .FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken);
@ -34,26 +40,26 @@ public class GetMarketerProfileQueryHandler(
if (marketer == null) if (marketer == null)
throw new BaseApiException(ApiResultStatusCode.MarketerNotFound,"Marketer not found" ,HttpStatusCode.NotFound); throw new BaseApiException(ApiResultStatusCode.MarketerNotFound,"Marketer not found" ,HttpStatusCode.NotFound);
var discount = await repositoryWrapper.SetRepository<Discount>() var discount = await _repositoryWrapper.SetRepository<Discount>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(d => d.MarketerId == marketer.Id, cancellationToken); .FirstOrDefaultAsync(d => d.MarketerId == marketer.Id, cancellationToken);
if (discount == null) if (discount == null)
throw new BaseApiException("Marketer has no discount"); throw new BaseApiException("Marketer has no discount");
var setting = (await settingService.GetSettingAsync(nameof(MarketerSetting), cancellationToken)) as MarketerSetting; var setting = (await _settingService.GetSettingAsync(nameof(MarketerSetting), cancellationToken)) as MarketerSetting;
if (setting == null) if (setting == null)
throw new BaseApiException("MarketerSetting is null"); throw new BaseApiException("MarketerSetting is null");
var response = new MarketerProfileResponseDto(); var response = new MarketerProfileResponseDto();
var orderCount = await repositoryWrapper.SetRepository<Order>() var orderCount = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.CountAsync(o => o.DiscountCode == discount.Code, cancellationToken); .CountAsync(o => o.DiscountCode == discount.Code, cancellationToken);
response.OrderCount = orderCount; response.OrderCount = orderCount;
var newTotalProductPrice = await repositoryWrapper.SetRepository<Order>() var newTotalProductPrice = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.Where(o => o.DiscountCode == discount.Code && o.OrderAt.Date > marketer.LastSettlement.Date) .Where(o => o.DiscountCode == discount.Code && o.OrderAt.Date > marketer.LastSettlement.Date)
.SumAsync(o => o.TotalProductsPrice, cancellationToken); .SumAsync(o => o.TotalProductsPrice, cancellationToken);

View File

@ -1,29 +1,36 @@
namespace Netina.Core.EntityServices.MarketerHandlers; namespace Netina.Core.EntityServices.MarketerHandlers;
public class SignUpMarketerCommandHandler( public class SignUpMarketerCommandHandler : IRequestHandler<SignUpMarketerCommand,MarketerProfileResponseDto>
UserManager<ApplicationUser> userManager,
IMediator mediator,
ICurrentUserService currentUserService,
IRepositoryWrapper repositoryWrapper)
: IRequestHandler<SignUpMarketerCommand, MarketerProfileResponseDto>
{ {
private readonly UserManager<ApplicationUser> _userManager;
private readonly IMediator _mediator;
private readonly ICurrentUserService _currentUserService;
private readonly IRepositoryWrapper _repositoryWrapper;
public SignUpMarketerCommandHandler(UserManager<ApplicationUser> userManager,IMediator mediator,ICurrentUserService currentUserService,IRepositoryWrapper repositoryWrapper)
{
_userManager = userManager;
_mediator = mediator;
_currentUserService = currentUserService;
_repositoryWrapper = repositoryWrapper;
}
public async Task<MarketerProfileResponseDto> Handle(SignUpMarketerCommand request, CancellationToken cancellationToken) public async Task<MarketerProfileResponseDto> Handle(SignUpMarketerCommand request, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("User id is null"); throw new AppException("User id is null");
if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new AppException("User id is wrong"); throw new AppException("User id is wrong");
var user = await userManager.FindByIdAsync(currentUserService.UserId); var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
if (user == null) if (user == null)
throw new AppException("User not found"); throw new AppException("User not found");
var marketer = await repositoryWrapper.SetRepository<Marketer>() var marketer = await _repositoryWrapper.SetRepository<Marketer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken); .FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken);
if (marketer != null) if (marketer != null)
return await mediator.Send(new GetMarketerProfileQuery(MarketerId: marketer.Id), cancellationToken); return await _mediator.Send(new GetMarketerProfileQuery(MarketerId: marketer.Id), cancellationToken);
marketer = new Marketer marketer = new Marketer
{ {
@ -31,16 +38,16 @@ public class SignUpMarketerCommandHandler(
FatherName = request.FatherName, FatherName = request.FatherName,
Shaba = request.Shaba, Shaba = request.Shaba,
}; };
repositoryWrapper.SetRepository<Marketer>() _repositoryWrapper.SetRepository<Marketer>()
.Add(marketer); .Add(marketer);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDate); user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDate);
user.NationalId = request.NationalId; user.NationalId = request.NationalId;
await userManager.UpdateAsync(user); await _userManager.UpdateAsync(user);
await mediator.Send(new CreateMarketerDiscountCommand(userId), cancellationToken); await _mediator.Send(new CreateMarketerDiscountCommand(userId), cancellationToken);
return await mediator.Send(new GetMarketerProfileQuery(marketer.Id), cancellationToken); return await _mediator.Send(new GetMarketerProfileQuery(marketer.Id), cancellationToken);
} }
} }

View File

@ -1,24 +1,31 @@
namespace Netina.Core.EntityServices.OrderBagHandlers; namespace Netina.Core.EntityServices.OrderBagHandlers;
public class AddToOrderBagCommandHandler( public class AddToOrderBagCommandHandler : IRequestHandler<AddToOrderBagCommand, OrderSDto>
IMediator mediator,
IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService)
: IRequestHandler<AddToOrderBagCommand, OrderSDto>
{ {
private readonly IMediator _mediator;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
public AddToOrderBagCommandHandler(IMediator mediator, IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService)
{
_mediator = mediator;
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
}
public async Task<OrderSDto> Handle(AddToOrderBagCommand request, CancellationToken cancellationToken) public async Task<OrderSDto> Handle(AddToOrderBagCommand request, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest); throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest);
if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new AppException("Customer id wrong", ApiResultStatusCode.BadRequest); throw new AppException("Customer id wrong", ApiResultStatusCode.BadRequest);
var orderBag = await mediator.Send(new GetUserOrderBagQuery(), cancellationToken); var orderBag = await _mediator.Send(new GetUserOrderBagQuery(), cancellationToken);
foreach (var requestDto in request.RequestDtos) foreach (var requestDto in request.RequestDtos)
{ {
var product = await repositoryWrapper.SetRepository<Product>() var product = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken); .FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken);
@ -28,16 +35,16 @@ public class AddToOrderBagCommandHandler(
throw new AppException("Product is not enable", ApiResultStatusCode.BadRequest); throw new AppException("Product is not enable", ApiResultStatusCode.BadRequest);
var productSDto = product.AdaptToSDto(); var productSDto = product.AdaptToSDto();
await mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken); await _mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
orderBag.AddToOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount, orderBag.AddToOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount,
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId,productSDto.BrandId, requestDto.Count); productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId, requestDto.Count);
} }
repositoryWrapper.SetRepository<Order>().Update(orderBag); _repositoryWrapper.SetRepository<Order>().Update(orderBag);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
var order = await mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken); var order = await _mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken);
return order.AdaptToSDto(); return order.AdaptToSDto();
} }

View File

@ -1,15 +1,22 @@
namespace Netina.Core.EntityServices.OrderBagHandlers; namespace Netina.Core.EntityServices.OrderBagHandlers;
public class CheckOrderBagCommandHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator) public class CheckOrderBagCommandHandler : IRequestHandler<CheckOrderBagCommand , List<CheckOrderBagResponseItem>>
: IRequestHandler<CheckOrderBagCommand, List<CheckOrderBagResponseItem>>
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
public CheckOrderBagCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
}
public async Task<List<CheckOrderBagResponseItem>> Handle(CheckOrderBagCommand request, CancellationToken cancellationToken) public async Task<List<CheckOrderBagResponseItem>> Handle(CheckOrderBagCommand request, CancellationToken cancellationToken)
{ {
List<CheckOrderBagResponseItem> response = new List<CheckOrderBagResponseItem>(); List<CheckOrderBagResponseItem> response = new List<CheckOrderBagResponseItem>();
foreach (var item in request.OrderBag) foreach (var item in request.OrderBag)
{ {
var product = await repositoryWrapper.SetRepository<Product>() var product = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.Where(p => p.Id == item.ProductId) .Where(p => p.Id == item.ProductId)
.Select(ProductMapper.ProjectToSDto) .Select(ProductMapper.ProjectToSDto)
@ -28,7 +35,7 @@ public class CheckOrderBagCommandHandler(IRepositoryWrapper repositoryWrapper, I
} }
else else
{ {
await mediator.Send(new CalculateProductDiscountCommand(product), cancellationToken); await _mediator.Send(new CalculateProductDiscountCommand(product), cancellationToken);
var res = new CheckOrderBagResponseItem var res = new CheckOrderBagResponseItem
{ {
ProductId = item.ProductId, ProductId = item.ProductId,

View File

@ -1,19 +1,25 @@
namespace Netina.Core.EntityServices.OrderBagHandlers; namespace Netina.Core.EntityServices.OrderBagHandlers;
public class GetUserOrderBagQueryHandler( public class GetUserOrderBagQueryHandler : IRequestHandler<GetUserOrderBagQuery,Order>
IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService,
IMediator mediator)
: IRequestHandler<GetUserOrderBagQuery, Order>
{ {
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
private readonly IMediator _mediator;
public GetUserOrderBagQueryHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService,IMediator mediator)
{
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
_mediator = mediator;
}
public async Task<Order> Handle(GetUserOrderBagQuery request, CancellationToken cancellationToken) public async Task<Order> Handle(GetUserOrderBagQuery request, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest); throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest);
if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new AppException("Customer id wrong",ApiResultStatusCode.BadRequest); throw new AppException("Customer id wrong",ApiResultStatusCode.BadRequest);
var customer = await repositoryWrapper.SetRepository<Customer>() var customer = await _repositoryWrapper.SetRepository<Customer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken); .FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken);
if (customer == null) if (customer == null)
@ -22,20 +28,20 @@ public class GetUserOrderBagQueryHandler(
{ {
UserId = userId UserId = userId
}; };
repositoryWrapper.SetRepository<Customer>() _repositoryWrapper.SetRepository<Customer>()
.Add(customer); .Add(customer);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
} }
var order = await repositoryWrapper.SetRepository<Order>() var order = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(o => o.CustomerId == customer.Id && o.OrderStatus == OrderStatus.OrderBag,cancellationToken); .FirstOrDefaultAsync(o => o.CustomerId == customer.Id && o.OrderStatus == OrderStatus.OrderBag,cancellationToken);
if (order == null) if (order == null)
order = await mediator.Send(new CreateBaseOrderCommand(userId),cancellationToken); order = await _mediator.Send(new CreateBaseOrderCommand(userId),cancellationToken);
else else
{ {
var orderProducts = await repositoryWrapper.SetRepository<OrderProduct>() var orderProducts = await _repositoryWrapper.SetRepository<OrderProduct>()
.TableNoTracking .TableNoTracking
.Where(op=>op.OrderId==order.Id) .Where(op=>op.OrderId==order.Id)
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);

View File

@ -1,23 +1,29 @@
namespace Netina.Core.EntityServices.OrderBagHandlers; namespace Netina.Core.EntityServices.OrderBagHandlers;
public class RemoveFromOrderBagCommandHandler( public class RemoveFromOrderBagCommandHandler : IRequestHandler<RemoveFromOrderBagCommand, OrderSDto>
ICurrentUserService currentUserService,
IRepositoryWrapper repositoryWrapper,
IMediator mediator)
: IRequestHandler<RemoveFromOrderBagCommand, OrderSDto>
{ {
private readonly ICurrentUserService _currentUserService;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
public RemoveFromOrderBagCommandHandler(ICurrentUserService currentUserService, IRepositoryWrapper repositoryWrapper,IMediator mediator)
{
_currentUserService = currentUserService;
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
}
public async Task<OrderSDto> Handle(RemoveFromOrderBagCommand request, CancellationToken cancellationToken) public async Task<OrderSDto> Handle(RemoveFromOrderBagCommand request, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest); throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest);
if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new AppException("Customer id wrong", ApiResultStatusCode.BadRequest); throw new AppException("Customer id wrong", ApiResultStatusCode.BadRequest);
var orderBag = await mediator.Send(new GetUserOrderBagQuery(), cancellationToken); var orderBag = await _mediator.Send(new GetUserOrderBagQuery(), cancellationToken);
foreach (var requestDto in request.RequestDtos) foreach (var requestDto in request.RequestDtos)
{ {
var product = await repositoryWrapper.SetRepository<Product>() var product = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken); .FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken);
@ -31,9 +37,9 @@ public class RemoveFromOrderBagCommandHandler(
} }
repositoryWrapper.SetRepository<Order>().Update(orderBag); _repositoryWrapper.SetRepository<Order>().Update(orderBag);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
var order = await mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken); var order = await _mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken);
return order.AdaptToSDto(); return order.AdaptToSDto();
} }

View File

@ -1,38 +0,0 @@
namespace Netina.Core.EntityServices.OrderBagHandlers;
public class SubmitDiscountActionCommandHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator)
: IRequestHandler<SubmitDiscountActionCommand, OrderSDto>
{
public async Task<OrderSDto> Handle(SubmitDiscountActionCommand request, CancellationToken cancellationToken)
{
var order = await repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
if (order == null)
throw new AppException("Order not found", ApiResultStatusCode.NotFound);
if (request.DiscountCode != null)
{
var discount = await repositoryWrapper.SetRepository<Discount>()
.TableNoTracking
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
if (discount == null || discount.IsExpired())
throw new AppException("تخفیف منقضی شده است یا وجود ندارد", ApiResultStatusCode.NotFound);
var isFirstUserOfDiscount = await mediator.Send(new CheckUserDiscountFirstUseCommand(request.DiscountCode), cancellationToken);
if (!isFirstUserOfDiscount)
throw new BaseApiException(ApiResultStatusCode.BadRequest, "شما یک بار از این کد تخفیف استفاده نموده اید و قابلیت استفاده مجدد ندارید");
order.SetDiscount(request.DiscountCode);
}
else
order.RemoveDiscount();
repositoryWrapper.SetRepository<Order>().Update(order);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
var calculateOrder = await mediator.Send(new CalculateOrderCommand(order.Id), cancellationToken);
return calculateOrder.AdaptToSDto();
}
}

View File

@ -0,0 +1,32 @@
namespace Netina.Core.EntityServices.OrderBagHandlers;
public class SubmitDiscountCommandHandler : IRequestHandler<SubmitDiscountCommand,OrderSDto>
{
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IMediator _mediator;
public SubmitDiscountCommandHandler(IRepositoryWrapper repositoryWrapper,IMediator mediator)
{
_repositoryWrapper = repositoryWrapper;
_mediator = mediator;
}
public async Task<OrderSDto> Handle(SubmitDiscountCommand request, CancellationToken cancellationToken)
{
var order = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
if (order == null)
throw new AppException("Order not found", ApiResultStatusCode.NotFound);
var discount = await _repositoryWrapper.SetRepository<Discount>()
.TableNoTracking
.FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken);
if (discount == null || discount.IsExpired())
throw new AppException("تخفیف منقضی شده است یا وجود ندارد", ApiResultStatusCode.NotFound);
order.SetDiscount(request.DiscountCode);
_repositoryWrapper.SetRepository<Order>().Update(order);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
var calculateOrder = await _mediator.Send(new CalculateOrderCommand(order.Id), cancellationToken);
return calculateOrder.AdaptToSDto();
}
}

View File

@ -1,24 +1,31 @@
namespace Netina.Core.EntityServices.OrderBagHandlers; namespace Netina.Core.EntityServices.OrderBagHandlers;
public class SubmitOrderBagCommandHandler( public class SubmitOrderBagCommandHandler : IRequestHandler<SubmitOrderBagCommand,OrderSDto>
IMediator mediator,
IRepositoryWrapper repositoryWrapper,
ICurrentUserService currentUserService)
: IRequestHandler<SubmitOrderBagCommand, OrderSDto>
{ {
private readonly IMediator _mediator;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ICurrentUserService _currentUserService;
public SubmitOrderBagCommandHandler(IMediator mediator, IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService)
{
_mediator = mediator;
_repositoryWrapper = repositoryWrapper;
_currentUserService = currentUserService;
}
public async Task<OrderSDto> Handle(SubmitOrderBagCommand request, CancellationToken cancellationToken) public async Task<OrderSDto> Handle(SubmitOrderBagCommand request, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest); throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest);
if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
throw new AppException("Customer id wrong", ApiResultStatusCode.BadRequest); throw new AppException("Customer id wrong", ApiResultStatusCode.BadRequest);
var orderBag = await mediator.Send(new GetUserOrderBagQuery(), cancellationToken); var orderBag = await _mediator.Send(new GetUserOrderBagQuery(), cancellationToken);
foreach (var requestDto in request.RequestDtos) foreach (var requestDto in request.RequestDtos)
{ {
var product = await repositoryWrapper.SetRepository<Product>() var product = await _repositoryWrapper.SetRepository<Product>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken); .FirstOrDefaultAsync(p => p.Id == requestDto.ProductId, cancellationToken);
@ -28,25 +35,25 @@ public class SubmitOrderBagCommandHandler(
throw new AppException("Product is not enable", ApiResultStatusCode.BadRequest); throw new AppException("Product is not enable", ApiResultStatusCode.BadRequest);
var productSDto = product.AdaptToSDto(); var productSDto = product.AdaptToSDto();
await mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken); await _mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
orderBag.ChangeOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount, orderBag.ChangeOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount,
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId,productSDto.BrandId, requestDto.Count); productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId, requestDto.Count);
} }
foreach (var orderProduct in orderBag.OrderProducts.ToList()) foreach (var orderProduct in orderBag.OrderProducts.ToList())
{ {
if(request.RequestDtos.FirstOrDefault(op=>op.ProductId==orderProduct.ProductId)==null) if(request.RequestDtos.FirstOrDefault(op=>op.ProductId==orderProduct.ProductId)==null)
{ {
orderBag.OrderProducts.Remove(orderProduct); orderBag.OrderProducts.Remove(orderProduct);
repositoryWrapper.SetRepository<OrderProduct>().Delete(orderProduct); _repositoryWrapper.SetRepository<OrderProduct>().Delete(orderProduct);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
} }
} }
repositoryWrapper.SetRepository<Order>().Update(orderBag); _repositoryWrapper.SetRepository<Order>().Update(orderBag);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
var order = await mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken); var order = await _mediator.Send(new CalculateOrderCommand(orderBag.Id), cancellationToken);
return order.AdaptToSDto(); return order.AdaptToSDto();
} }

View File

@ -2,19 +2,26 @@
namespace Netina.Core.EntityServices.OrderBagHandlers; namespace Netina.Core.EntityServices.OrderBagHandlers;
public class SubmitOrderDeliveryCommandHandler(IMediator mediator, IRepositoryWrapper repositoryWrapper) public class SubmitOrderDeliveryCommandHandler : IRequestHandler<SubmitOrderDeliveryCommand, OrderSDto>
: IRequestHandler<SubmitOrderDeliveryCommand, OrderSDto>
{ {
private readonly IMediator _mediator;
private readonly IRepositoryWrapper _repositoryWrapper;
public SubmitOrderDeliveryCommandHandler(IMediator mediator, IRepositoryWrapper repositoryWrapper)
{
_mediator = mediator;
_repositoryWrapper = repositoryWrapper;
}
public async Task<OrderSDto> Handle(SubmitOrderDeliveryCommand request, CancellationToken cancellationToken) public async Task<OrderSDto> Handle(SubmitOrderDeliveryCommand request, CancellationToken cancellationToken)
{ {
var order = await repositoryWrapper.SetRepository<Order>() var order = await _repositoryWrapper.SetRepository<Order>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken); .FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
if (order == null) if (order == null)
throw new AppException("Order not found", ApiResultStatusCode.NotFound); throw new AppException("Order not found", ApiResultStatusCode.NotFound);
var orderDelivery = await repositoryWrapper.SetRepository<OrderDelivery>() var orderDelivery = await _repositoryWrapper.SetRepository<OrderDelivery>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(od => od.OrderId == request.OrderId, cancellationToken); .FirstOrDefaultAsync(od => od.OrderId == request.OrderId, cancellationToken);
if (orderDelivery != null) if (orderDelivery != null)
@ -22,7 +29,7 @@ public class SubmitOrderDeliveryCommandHandler(IMediator mediator, IRepositoryWr
order.AddOrderDelivery(orderDelivery.AddressId, orderDelivery.DeliveryCost, orderDelivery.ShippingId, orderDelivery.OrderId, orderDelivery.Id); order.AddOrderDelivery(orderDelivery.AddressId, orderDelivery.DeliveryCost, orderDelivery.ShippingId, orderDelivery.OrderId, orderDelivery.Id);
} }
var shipping = await repositoryWrapper.SetRepository<Shipping>() var shipping = await _repositoryWrapper.SetRepository<Shipping>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(s => s.Id == request.ShippingId, cancellationToken); .FirstOrDefaultAsync(s => s.Id == request.ShippingId, cancellationToken);
if (shipping == null) if (shipping == null)
@ -30,10 +37,10 @@ public class SubmitOrderDeliveryCommandHandler(IMediator mediator, IRepositoryWr
order.AddOrderDelivery(request.AddressId, shipping.DeliveryCost, request.ShippingId, request.OrderId); order.AddOrderDelivery(request.AddressId, shipping.DeliveryCost, request.ShippingId, request.OrderId);
repositoryWrapper.SetRepository<Order>().Update(order); _repositoryWrapper.SetRepository<Order>().Update(order);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
var calculatedOrder = await mediator.Send(new CalculateOrderCommand(order.Id), cancellationToken); var calculatedOrder = await _mediator.Send(new CalculateOrderCommand(order.Id), cancellationToken);
return calculatedOrder.AdaptToSDto(); return calculatedOrder.AdaptToSDto();
} }
} }

View File

@ -1,14 +1,10 @@
namespace Netina.Core.EntityServices.OrderHandlers; namespace Netina.Core.EntityServices.OrderHandlers;
public class CalculateOrderCommandHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator,ISettingService settingService) : IRequestHandler<CalculateOrderCommand,Order> public class CalculateOrderCommandHandler(IRepositoryWrapper repositoryWrapper, IMediator mediator) : IRequestHandler<CalculateOrderCommand,Order>
{ {
public async Task<Order> Handle(CalculateOrderCommand request, CancellationToken cancellationToken) public async Task<Order> Handle(CalculateOrderCommand request, CancellationToken cancellationToken)
{ {
var setting = await settingService.GetSettingAsync("ShopSetting", cancellationToken);
double taxesFee = 9;
if (setting is ShopSetting shopSetting)
taxesFee = shopSetting.TaxesFee;
var order = await mediator.Send(new GetOrderQuery(request.OrderId), cancellationToken); var order = await mediator.Send(new GetOrderQuery(request.OrderId), cancellationToken);
if (order.OrderStatus != OrderStatus.OrderBag) if (order.OrderStatus != OrderStatus.OrderBag)
throw new AppException("Order is not in bag status and cant be calculate", ApiResultStatusCode.BadRequest); throw new AppException("Order is not in bag status and cant be calculate", ApiResultStatusCode.BadRequest);
@ -23,21 +19,12 @@ public class CalculateOrderCommandHandler(IRepositoryWrapper repositoryWrapper,
var deliveryPrice = order.OrderDelivery?.DeliveryCost ?? 0; var deliveryPrice = order.OrderDelivery?.DeliveryCost ?? 0;
double productDiscountPrice = order.OrderProducts.Sum(op=>(op.ProductFee - op.ProductFeeWithDiscount) * op.Count); double productDiscountPrice = order.OrderProducts.Sum(op=>(op.ProductFee - op.ProductFeeWithDiscount) * op.Count);
double discountCodePrice = 0; double discountCodePrice = 0;
try
{
if (!order.DiscountCode.IsNullOrEmpty()) if (!order.DiscountCode.IsNullOrEmpty())
discountCodePrice += await mediator.Send(new CalculateOrderDiscountCommand(order.DiscountCode, order), discountCodePrice += await mediator.Send(new CalculateOrderDiscountCommand(order.DiscountCode, order),cancellationToken);
cancellationToken);
}
catch (Exception )
{
order.RemoveDiscount();
}
if (totalProductPrice > 5000000) //var taxesPrice = (((totalProductPrice - discountPrice) + totalPackingPrice + servicePrice) / 100) * _shopSettings.TaxesFee;
deliveryPrice = 0;
var taxesPrice = (((totalProductPrice - (discountCodePrice + productDiscountPrice)) + totalPackingPrice + servicePrice) / 100) * taxesFee; var taxesPrice = 0;
order.SetTotalPrice(totalProductPrice, totalPackingPrice, servicePrice, deliveryPrice, productDiscountPrice, discountCodePrice, taxesPrice); order.SetTotalPrice(totalProductPrice, totalPackingPrice, servicePrice, deliveryPrice, productDiscountPrice, discountCodePrice, taxesPrice);
order.OrderProducts.Clear(); order.OrderProducts.Clear();

View File

@ -1,21 +0,0 @@
namespace Netina.Core.EntityServices.OrderHandlers;
public class CancelOrderStepCommandHandler (IRepositoryWrapper repositoryWrapper) : IRequestHandler<CancelOrderStepCommand,bool>
{
public async Task<bool> Handle(CancelOrderStepCommand request, CancellationToken cancellationToken)
{
var order = await repositoryWrapper.SetRepository<Order>()
.TableNoTracking
.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
if (order == null)
throw new AppException("Order not found", ApiResultStatusCode.NotFound);
order.SetOrderStatus(OrderStatus.Canceled);
repositoryWrapper.SetRepository<Order>().Update(order);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
return true;
}
}

View File

@ -0,0 +1,23 @@
namespace Netina.Core.EntityServices.ReviewHandlers;
public class ConfirmReviewCommandHandler : IRequestHandler<ConfirmReviewCommand , bool>
{
private readonly IRepositoryWrapper _repositoryWrapper;
public ConfirmReviewCommandHandler(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
public async Task<bool> Handle(ConfirmReviewCommand request, CancellationToken cancellationToken)
{
var review = await _repositoryWrapper.SetRepository<Review>().TableNoTracking
.FirstOrDefaultAsync(r => r.Id == request.Id, cancellationToken);
if (review == null)
throw new AppException("Review not found", ApiResultStatusCode.NotFound);
review.ConfirmReview();
_repositoryWrapper.SetRepository<Review>().Update(review);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
return true;
}
}

View File

@ -1,19 +1,33 @@
namespace Netina.Core.EntityServices; namespace Netina.Core.EntityServices;
public class UserService( public class UserService : IUserService
ICurrentUserService currentUserService, {
private readonly ICurrentUserService _currentUserService;
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly IExternalFilesService _externalFilesService;
private readonly IRepositoryWrapper _repositoryWrapper;
public UserService(ICurrentUserService currentUserService,
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager, RoleManager<ApplicationRole> roleManager,
IExternalFilesService externalFilesService, IExternalFilesService externalFilesService,
IRepositoryWrapper repositoryWrapper) IRepositoryWrapper repositoryWrapper)
: IUserService
{ {
_currentUserService = currentUserService;
_userManager = userManager;
_roleManager = roleManager;
_externalFilesService = externalFilesService;
_repositoryWrapper = repositoryWrapper;
}
public async Task<ProfileResponseDto> GetUserProfileAsync(CancellationToken cancellationToken) public async Task<ProfileResponseDto> GetUserProfileAsync(CancellationToken cancellationToken)
{ {
if (!Guid.TryParse(currentUserService.UserId, out var userId)) if (!Guid.TryParse(_currentUserService.UserId, out var userId))
throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized);
var user = await userManager.FindByIdAsync(userId.ToString()); var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null) if (user == null)
throw new AppException("User NotFound", ApiResultStatusCode.NotFound); throw new AppException("User NotFound", ApiResultStatusCode.NotFound);
@ -22,14 +36,14 @@ public class UserService(
//var userSDto = user.AdaptToSDto(); //var userSDto = user.AdaptToSDto();
response.User = new ApplicationUserSDto(); response.User = new ApplicationUserSDto();
var userRoles = await userManager.GetRolesAsync(user); var userRoles = await _userManager.GetRolesAsync(user);
foreach (var role in userRoles) foreach (var role in userRoles)
{ {
var dbRole = await roleManager.FindByNameAsync(role); var dbRole = await _roleManager.FindByNameAsync(role);
if (dbRole != null) if (dbRole != null)
{ {
var roleClaims = await roleManager.GetClaimsAsync(dbRole); var roleClaims = await _roleManager.GetClaimsAsync(dbRole);
response.Permissions.AddRange(roleClaims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList()); response.Permissions.AddRange(roleClaims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList());
} }
} }
@ -43,23 +57,23 @@ public class UserService(
List<ApplicationUserSDto> users; List<ApplicationUserSDto> users;
if (phoneNumber == null || phoneNumber.IsNullOrEmpty()) if (phoneNumber == null || phoneNumber.IsNullOrEmpty())
users = await userManager.Users users = await _userManager.Users
.Where(u => u.UserName != "09214802813") .Where(u => u.UserName != "09214802813")
.Skip(page * 15).Take(15) .Skip(page * 15).Take(15)
.Select(ApplicationUserMapper.ProjectToSDto) .Select(ApplicationUserMapper.ProjectToSDto)
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);
else else
users = await userManager.Users users = await _userManager.Users
.Where(a => a.PhoneNumber == phoneNumber && a.UserName != "09214802813") .Where(a => a.PhoneNumber == phoneNumber && a.UserName != "09214802813")
.Skip(page * 15).Take(15) .Skip(page * 15).Take(15)
.Select(ApplicationUserMapper.ProjectToSDto) .Select(ApplicationUserMapper.ProjectToSDto)
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);
foreach (var user in users) foreach (var user in users)
{ {
var roles = await userManager.GetRolesAsync(user.AdaptToApplicationUser()); var roles = await _userManager.GetRolesAsync(user.AdaptToApplicationUser());
foreach (var roleName in roles) foreach (var roleName in roles)
{ {
var role = await roleManager.FindByNameAsync(roleName); var role = await _roleManager.FindByNameAsync(roleName);
if (role != null) if (role != null)
user.RoleName += role.PersianName + " "; user.RoleName += role.PersianName + " ";
} }
@ -71,20 +85,20 @@ public class UserService(
public async Task<ApplicationUserSDto> GetUserAsync(Guid userId, CancellationToken cancellationToken = default) public async Task<ApplicationUserSDto> GetUserAsync(Guid userId, CancellationToken cancellationToken = default)
{ {
var user = await userManager.FindByIdAsync(userId.ToString()); var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null) if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
var dto = user.AdaptToSDto(); var dto = user.AdaptToSDto();
dto.IsMarketer = await repositoryWrapper.SetRepository<Marketer>() dto.IsMarketer = await _repositoryWrapper.SetRepository<Marketer>()
.TableNoTracking .TableNoTracking
.AnyAsync(m => m.UserId == userId, cancellationToken); .AnyAsync(m => m.UserId == userId, cancellationToken);
dto.IsManager = await repositoryWrapper.SetRepository<Manager>() dto.IsManager = await _repositoryWrapper.SetRepository<Manager>()
.TableNoTracking .TableNoTracking
.AnyAsync(m => m.UserId == userId, cancellationToken); .AnyAsync(m => m.UserId == userId, cancellationToken);
var roles = await userManager.GetRolesAsync(user); var roles = await _userManager.GetRolesAsync(user);
foreach (var roleName in roles) foreach (var roleName in roles)
{ {
var role = await roleManager.FindByNameAsync(roleName); var role = await _roleManager.FindByNameAsync(roleName);
if (role != null) if (role != null)
dto.RoleIds.Add(role.Id); dto.RoleIds.Add(role.Id);
} }
@ -99,7 +113,7 @@ public class UserService(
PhoneNumber = phoneNumber, PhoneNumber = phoneNumber,
SignUpStatus = SignUpStatus.StartSignOn SignUpStatus = SignUpStatus.StartSignOn
}; };
var result = await userManager.CreateAsync(user); var result = await _userManager.CreateAsync(user);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors)); throw new AppException(string.Join('|', result.Errors));
return user; return user;
@ -108,7 +122,7 @@ public class UserService(
public async Task<ApplicationUser> CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken) public async Task<ApplicationUser> CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken)
{ {
var user = await userManager.FindByNameAsync(request.PhoneNumber); var user = await _userManager.FindByNameAsync(request.PhoneNumber);
if (user == null) if (user == null)
{ {
user = new ApplicationUser user = new ApplicationUser
@ -126,13 +140,13 @@ public class UserService(
if (!request.Password.IsNullOrEmpty()) if (!request.Password.IsNullOrEmpty())
{ {
var result = await userManager.CreateAsync(user, request.Password); var result = await _userManager.CreateAsync(user, request.Password);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
} }
else else
{ {
var result = await userManager.CreateAsync(user); var result = await _userManager.CreateAsync(user);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
} }
@ -141,31 +155,31 @@ public class UserService(
{ {
foreach (var roleId in request.RoleIds) foreach (var roleId in request.RoleIds)
{ {
var role = await roleManager.FindByIdAsync(roleId.ToString()); var role = await _roleManager.FindByIdAsync(roleId.ToString());
if (role is { Name: not null }) if (role is { Name: not null })
await userManager.AddToRoleAsync(user, role.Name); await _userManager.AddToRoleAsync(user, role.Name);
} }
} }
var customer = await repositoryWrapper.SetRepository<Customer>() var customer = await _repositoryWrapper.SetRepository<Customer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == user.Id, cancellationToken); .FirstOrDefaultAsync(c => c.UserId == user.Id, cancellationToken);
if (customer != null) if (customer != null)
{ {
repositoryWrapper.SetRepository<Customer>() _repositoryWrapper.SetRepository<Customer>()
.Add(new Customer .Add(new Customer
{ {
UserId = user.Id UserId = user.Id
}); });
await repositoryWrapper.SaveChangesAsync(default); await _repositoryWrapper.SaveChangesAsync(default);
} }
repositoryWrapper.SetRepository<Manager>() _repositoryWrapper.SetRepository<Manager>()
.Add(new Manager .Add(new Manager
{ {
UserId = user.Id UserId = user.Id
}); });
await repositoryWrapper.SaveChangesAsync(default); await _repositoryWrapper.SaveChangesAsync(default);
} }
return user; return user;
} }
@ -175,7 +189,7 @@ public class UserService(
if (request.UserId == Guid.Empty) if (request.UserId == Guid.Empty)
throw new AppException("Wrong authorize token , UserId needed"); throw new AppException("Wrong authorize token , UserId needed");
var user = await userManager.FindByIdAsync(request.UserId.ToString()); var user = await _userManager.FindByIdAsync(request.UserId.ToString());
if (user == null) if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
user.LastName = request.LastName; user.LastName = request.LastName;
@ -188,29 +202,29 @@ public class UserService(
user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp); user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp);
user.Gender = request.Gender; user.Gender = request.Gender;
var result = await userManager.UpdateAsync(user); var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
if (!request.Password.IsNullOrEmpty()) if (!request.Password.IsNullOrEmpty())
{ {
if (await userManager.HasPasswordAsync(user)) if (await _userManager.HasPasswordAsync(user))
await userManager.RemovePasswordAsync(user); await _userManager.RemovePasswordAsync(user);
var addPassResult = await userManager.AddPasswordAsync(user, request.Password); var addPassResult = await _userManager.AddPasswordAsync(user, request.Password);
if (!addPassResult.Succeeded) if (!addPassResult.Succeeded)
throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description)));
} }
if (request.RoleIds.Count > 0) if (request.RoleIds.Count > 0)
{ {
var userRoles = await userManager.GetRolesAsync(user); var userRoles = await _userManager.GetRolesAsync(user);
await userManager.RemoveFromRolesAsync(user, userRoles); await _userManager.RemoveFromRolesAsync(user, userRoles);
foreach (var roleId in request.RoleIds) foreach (var roleId in request.RoleIds)
{ {
var role = await roleManager.FindByIdAsync(roleId.ToString()); var role = await _roleManager.FindByIdAsync(roleId.ToString());
if (role is { Name: not null }) if (role is { Name: not null })
{ {
await userManager.AddToRoleAsync(user, role.Name); await _userManager.AddToRoleAsync(user, role.Name);
} }
} }
} }
@ -220,10 +234,10 @@ public class UserService(
public async Task<bool> EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken) public async Task<bool> EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken)
{ {
if (currentUserService.UserId == null) if (_currentUserService.UserId == null)
throw new AppException("Wrong authorize token , UserId needed"); throw new AppException("Wrong authorize token , UserId needed");
var user = await userManager.FindByIdAsync(currentUserService.UserId); var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
if (user == null) if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
user.LastName = request.LastName; user.LastName = request.LastName;
@ -236,15 +250,15 @@ public class UserService(
user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp); user.BirthDate = DateTimeExtensions.UnixTimeStampToDateTime(request.BirthDateTimeStamp);
user.Gender = request.Gender; user.Gender = request.Gender;
var result = await userManager.UpdateAsync(user); var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded) if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', result.Errors.Select(e => e.Description)));
if (!request.Password.IsNullOrEmpty()) if (!request.Password.IsNullOrEmpty())
{ {
if (await userManager.HasPasswordAsync(user)) if (await _userManager.HasPasswordAsync(user))
await userManager.RemovePasswordAsync(user); await _userManager.RemovePasswordAsync(user);
var addPassResult = await userManager.AddPasswordAsync(user, request.Password); var addPassResult = await _userManager.AddPasswordAsync(user, request.Password);
if (!addPassResult.Succeeded) if (!addPassResult.Succeeded)
throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', addPassResult.Errors.Select(e => e.Description)));
} }
@ -254,34 +268,34 @@ public class UserService(
public async Task<bool> RemoveUserAsync(Guid userId, CancellationToken cancellationToken) public async Task<bool> RemoveUserAsync(Guid userId, CancellationToken cancellationToken)
{ {
var user = await userManager.FindByIdAsync(userId.ToString()); var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null) if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
var roles = await userManager.GetRolesAsync(user); var roles = await _userManager.GetRolesAsync(user);
await userManager.RemoveFromRolesAsync(user, roles); await _userManager.RemoveFromRolesAsync(user, roles);
var removeResult = await userManager.DeleteAsync(user); var removeResult = await _userManager.DeleteAsync(user);
if (!removeResult.Succeeded) if (!removeResult.Succeeded)
throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description)));
var customer = await repositoryWrapper.SetRepository<Customer>() var customer = await _repositoryWrapper.SetRepository<Customer>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken); .FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken);
if (customer != null) if (customer != null)
{ {
repositoryWrapper.SetRepository<Customer>() _repositoryWrapper.SetRepository<Customer>()
.Delete(customer); .Delete(customer);
await repositoryWrapper.SaveChangesAsync(default); await _repositoryWrapper.SaveChangesAsync(default);
} }
var manager = await repositoryWrapper.SetRepository<Manager>() var manager = await _repositoryWrapper.SetRepository<Manager>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken); .FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken);
if (manager != null) if (manager != null)
{ {
repositoryWrapper.SetRepository<Manager>() _repositoryWrapper.SetRepository<Manager>()
.Delete(manager); .Delete(manager);
await repositoryWrapper.SaveChangesAsync(default); await _repositoryWrapper.SaveChangesAsync(default);
} }
return true; return true;
@ -289,26 +303,26 @@ public class UserService(
public async Task<AdminChangeLogResponseDto> GetAdminChangeLogAsync(CancellationToken cancellationToken = default) public async Task<AdminChangeLogResponseDto> GetAdminChangeLogAsync(CancellationToken cancellationToken = default)
{ {
if (!Guid.TryParse(currentUserService.UserId, out var userId)) if (!Guid.TryParse(_currentUserService.UserId, out var userId))
throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized);
var user = await userManager.FindByIdAsync(userId.ToString()); var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null) if (user == null)
throw new AppException("User NotFound", ApiResultStatusCode.NotFound); throw new AppException("User NotFound", ApiResultStatusCode.NotFound);
var manager = await repositoryWrapper.SetRepository<Manager>() var manager = await _repositoryWrapper.SetRepository<Manager>()
.TableNoTracking .TableNoTracking
.FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken); .FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken);
var currentVersion = await externalFilesService.GetAdminChangeLogAsync(cancellationToken); var currentVersion = await _externalFilesService.GetAdminChangeLogAsync(cancellationToken);
if (manager != null) if (manager != null)
{ {
if (!(manager.LatestVersionUsed < currentVersion.VersionNumber)) return currentVersion; if (!(manager.LatestVersionUsed < currentVersion.VersionNumber)) return currentVersion;
currentVersion.IsNewVersion = true; currentVersion.IsNewVersion = true;
manager.LatestVersionUsed = currentVersion.VersionNumber; manager.LatestVersionUsed = currentVersion.VersionNumber;
repositoryWrapper.SetRepository<Manager>() _repositoryWrapper.SetRepository<Manager>()
.Update(manager); .Update(manager);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await _repositoryWrapper.SaveChangesAsync(cancellationToken);
} }
return currentVersion; return currentVersion;
@ -317,7 +331,7 @@ public class UserService(
public async Task<List<ApplicationRole>> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default) public async Task<List<ApplicationRole>> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default)
{ {
var roles = await roleManager.Roles var roles = await _roleManager.Roles
.Where(r => r.Name != "RootAdmin") .Where(r => r.Name != "RootAdmin")
.Skip(page * 15) .Skip(page * 15)
.Take(15) .Take(15)
@ -329,9 +343,9 @@ public class UserService(
{ {
IQueryable<ApplicationRole> roles; IQueryable<ApplicationRole> roles;
if (roleName != null) if (roleName != null)
roles = roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.Name != "Customer" && r.PersianName.Trim().ToLower().Contains(roleName)); roles = _roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.Name != "Customer" && r.PersianName.Trim().ToLower().Contains(roleName));
else else
roles = roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.Name != "Customer"); roles = _roleManager.Roles.Where(r => r.Name != "RootAdmin" && r.Name != "Customer");
if (page != null) if (page != null)
roles = roles.Skip(page.Value * 15).Take(15); roles = roles.Skip(page.Value * 15).Take(15);
else else
@ -341,13 +355,13 @@ public class UserService(
public async Task<RoleActionRequestDto> GetRoleAsync(Guid roleId, CancellationToken cancellationToken = default) public async Task<RoleActionRequestDto> GetRoleAsync(Guid roleId, CancellationToken cancellationToken = default)
{ {
var role = (await roleManager.FindByIdAsync(roleId.ToString())); var role = (await _roleManager.FindByIdAsync(roleId.ToString()));
if (role == null) if (role == null)
throw new AppException("نقش پیدا نشد", ApiResultStatusCode.NotFound); throw new AppException("نقش پیدا نشد", ApiResultStatusCode.NotFound);
var roleDto = role.Adapt<RoleActionRequestDto>(); var roleDto = role.Adapt<RoleActionRequestDto>();
roleDto.RoleId = roleId; roleDto.RoleId = roleId;
roleDto.Permissions = (await roleManager.GetClaimsAsync(role)) roleDto.Permissions = (await _roleManager.GetClaimsAsync(role))
.Where(c => c.Type == CustomClaimType.Permission) .Where(c => c.Type == CustomClaimType.Permission)
.Select(c => c.Value) .Select(c => c.Value)
.ToList(); .ToList();
@ -366,12 +380,12 @@ public class UserService(
Description = request.Description, Description = request.Description,
Name = $"{request.EnglishName}" Name = $"{request.EnglishName}"
}; };
var createRoleResult = await roleManager.CreateAsync(applicationRole); var createRoleResult = await _roleManager.CreateAsync(applicationRole);
if (!createRoleResult.Succeeded) if (!createRoleResult.Succeeded)
throw new AppException(string.Join('|', createRoleResult.Errors)); throw new AppException(string.Join('|', createRoleResult.Errors));
foreach (var claim in request.Permissions) foreach (var claim in request.Permissions)
await roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim)); await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim));
return applicationRole; return applicationRole;
} }
@ -379,7 +393,7 @@ public class UserService(
{ {
if (request.EnglishName.IsNullOrEmpty()) if (request.EnglishName.IsNullOrEmpty())
throw new AppException("لطفا نام انگلیسی را وارد کنید"); throw new AppException("لطفا نام انگلیسی را وارد کنید");
var applicationRole = await roleManager.FindByIdAsync(request.RoleId.ToString()); var applicationRole = await _roleManager.FindByIdAsync(request.RoleId.ToString());
if (applicationRole == null) if (applicationRole == null)
throw new AppException("نقش پیدا نشد"); throw new AppException("نقش پیدا نشد");
@ -388,20 +402,20 @@ public class UserService(
applicationRole.Description = request.Description; applicationRole.Description = request.Description;
applicationRole.Name = $"{request.EnglishName}"; applicationRole.Name = $"{request.EnglishName}";
var createRoleResult = await roleManager.UpdateAsync(applicationRole); var createRoleResult = await _roleManager.UpdateAsync(applicationRole);
if (!createRoleResult.Succeeded) if (!createRoleResult.Succeeded)
throw new AppException(string.Join('|', createRoleResult.Errors)); throw new AppException(string.Join('|', createRoleResult.Errors));
var roleClaims = (await roleManager.GetClaimsAsync(applicationRole)).Where(c => c.Type == CustomClaimType.Permission).ToList(); var roleClaims = (await _roleManager.GetClaimsAsync(applicationRole)).Where(c => c.Type == CustomClaimType.Permission).ToList();
foreach (var roleClaim in roleClaims.ToList()) foreach (var roleClaim in roleClaims.ToList())
{ {
var removeResult = await roleManager.RemoveClaimAsync(applicationRole, roleClaim); var removeResult = await _roleManager.RemoveClaimAsync(applicationRole, roleClaim);
if (!removeResult.Succeeded) if (!removeResult.Succeeded)
throw new AppException(string.Join(" | ", removeResult.Errors.Select(e => e.Description))); throw new AppException(string.Join(" | ", removeResult.Errors.Select(e => e.Description)));
} }
foreach (var claim in request.Permissions) foreach (var claim in request.Permissions)
{ {
var addResult = await roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim)); var addResult = await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim));
if (!addResult.Succeeded) if (!addResult.Succeeded)
throw new AppException(string.Join(" | ", addResult.Errors.Select(e => e.Description))); throw new AppException(string.Join(" | ", addResult.Errors.Select(e => e.Description)));
} }
@ -411,18 +425,18 @@ public class UserService(
public async Task<bool> RemoveRoleAsync(Guid roleId, CancellationToken cancellationToken = default) public async Task<bool> RemoveRoleAsync(Guid roleId, CancellationToken cancellationToken = default)
{ {
var applicationRole = await roleManager.FindByIdAsync(roleId.ToString()); var applicationRole = await _roleManager.FindByIdAsync(roleId.ToString());
if (applicationRole == null) if (applicationRole == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound); throw new AppException("User not found", ApiResultStatusCode.NotFound);
var claims = await roleManager.GetClaimsAsync(applicationRole); var claims = await _roleManager.GetClaimsAsync(applicationRole);
foreach (var claim in claims) foreach (var claim in claims)
await roleManager.RemoveClaimAsync(applicationRole, claim); await _roleManager.RemoveClaimAsync(applicationRole, claim);
var users = await userManager.GetUsersInRoleAsync(applicationRole.Name); var users = await _userManager.GetUsersInRoleAsync(applicationRole.Name);
foreach (var user in users) foreach (var user in users)
await userManager.RemoveFromRoleAsync(user, applicationRole.Name); await _userManager.RemoveFromRoleAsync(user, applicationRole.Name);
var removeResult = await roleManager.DeleteAsync(applicationRole); var removeResult = await _roleManager.DeleteAsync(applicationRole);
if (!removeResult.Succeeded) if (!removeResult.Succeeded)
throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description))); throw new AppException(string.Join('|', removeResult.Errors.Select(e => e.Description)));
return true; return true;

View File

@ -1,11 +1,18 @@
namespace Netina.Core.Models.Api; namespace Netina.Core.Models.Api;
public class ApiResult(bool isSuccess, ApiResultStatusCode statusCode, string message = null) public class ApiResult
{ {
public bool IsSuccess { get; set; } = isSuccess; public ApiResult(bool isSuccess, ApiResultStatusCode statusCode, string message = null)
public ApiResultStatusCode StatusCode { get; set; } = statusCode; {
IsSuccess = isSuccess;
StatusCode = statusCode;
Message = message ?? statusCode.ToDisplay();
}
public bool IsSuccess { get; set; }
public ApiResultStatusCode StatusCode { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Message { get; set; } = message ?? statusCode.ToDisplay(); public string Message { get; set; }
#region Implicit Operators #region Implicit Operators
@ -54,12 +61,17 @@ public class ApiResult(bool isSuccess, ApiResultStatusCode statusCode, string me
#endregion #endregion
} }
public class ApiResult<TData>(bool isSuccess, ApiResultStatusCode statusCode, TData data, string message = null) public class ApiResult<TData> : ApiResult
: ApiResult(isSuccess, statusCode, message)
where TData : class where TData : class
{ {
public ApiResult(bool isSuccess, ApiResultStatusCode statusCode, TData data, string message = null)
: base(isSuccess, statusCode, message)
{
Data = data;
}
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public TData Data { get; set; } = data; public TData Data { get; set; }
#region Implicit Operators #region Implicit Operators

View File

@ -7,12 +7,12 @@ public static class SiteMapUIds
public const string BlogCategories = "B5FF333DC4FF4BB4A309CE3AA32CE45A"; public const string BlogCategories = "B5FF333DC4FF4BB4A309CE3AA32CE45A";
public const string Pages = "B463B6C4CC53432C822D79934F528D3E"; public const string Pages = "B463B6C4CC53432C822D79934F528D3E";
public static List<string> AllSiteMapsUIds => public static List<string> AllSiteMapsUIds => new List<string>
[ {
BlogCategories, BlogCategories,
Categories, Categories,
Blogs, Blogs,
Brands, Brands,
Pages Pages
]; };
} }

View File

@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
@ -13,9 +12,9 @@
<PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" /> <PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" />
<PackageReference Include="Autofac.Extras.Quartz" Version="10.0.0" /> <PackageReference Include="Autofac.Extras.Quartz" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
<PackageReference Include="Quartz" Version="3.13.0" /> <PackageReference Include="Quartz" Version="3.8.1" />
<PackageReference Include="Syncfusion.Pdf.Net.Core" Version="27.1.50" /> <PackageReference Include="Syncfusion.Pdf.Net.Core" Version="24.1.41" />
</ItemGroup> </ItemGroup>
@ -27,6 +26,7 @@
<ItemGroup> <ItemGroup>
<Folder Include="CoreServices\WebSiteServices\" /> <Folder Include="CoreServices\WebSiteServices\" />
<Folder Include="EntityServices\ProductHandlers\" /> <Folder Include="EntityServices\ProductHandlers\" />
<Folder Include="EntityServices\ReviewHandlers\" />
<Folder Include="Models\Api\" /> <Folder Include="Models\Api\" />
<Folder Include="Models\Scraper\" /> <Folder Include="Models\Scraper\" />
<Folder Include="Utilities\" /> <Folder Include="Utilities\" />

View File

@ -3,11 +3,20 @@ using Quartz;
namespace Netina.Core.QuartzServices; namespace Netina.Core.QuartzServices;
public class JobScheduler(IScheduler scheduler, ILogger<JobScheduler> logger) public class JobScheduler
{ {
private readonly IScheduler _scheduler;
private readonly ILogger<JobScheduler> _logger;
public JobScheduler(IScheduler scheduler, ILogger<JobScheduler> logger)
{
_scheduler = scheduler;
_logger = logger;
}
public void Start() public void Start()
{ {
scheduler.Start(); _scheduler.Start();
IJobDetail job = JobBuilder.Create<SiteMapScheduledJob>() IJobDetail job = JobBuilder.Create<SiteMapScheduledJob>()
.WithIdentity("SiteMapJob", "admin") .WithIdentity("SiteMapJob", "admin")
@ -24,10 +33,10 @@ public class JobScheduler(IScheduler scheduler, ILogger<JobScheduler> logger)
DayOfWeek.Friday)) DayOfWeek.Friday))
.StartNow() .StartNow()
.Build(); .Build();
var offset = scheduler.ScheduleJob(job, trigger); var offset = _scheduler.ScheduleJob(job, trigger);
logger.LogInformation($"======== Table Schedulers Set For {offset.Result.ToString()} IN {DateTime.Now.ToString()} ==========="); _logger.LogInformation($"======== Table Schedulers Set For {offset.Result.ToString()} IN {DateTime.Now.ToString()} ===========");
} }
} }

View File

@ -3,11 +3,20 @@ using Quartz;
namespace Netina.Core.QuartzServices; namespace Netina.Core.QuartzServices;
public class SiteMapScheduledJob(ILogger<SiteMapScheduledJob> logger, ISiteMapService siteMapService) : IJob public class SiteMapScheduledJob : IJob
{ {
private readonly ILogger<SiteMapScheduledJob> _logger;
private readonly ISiteMapService _siteMapService;
public SiteMapScheduledJob(ILogger<SiteMapScheduledJob> logger,ISiteMapService siteMapService)
{
_logger = logger;
_siteMapService = siteMapService;
}
public async Task Execute(IJobExecutionContext context) public async Task Execute(IJobExecutionContext context)
{ {
await siteMapService.CreateSiteMapAsync(); await _siteMapService.CreateSiteMapAsync();
logger.LogInformation($"Site Map Job Done At : {DateTime.Now}"); _logger.LogInformation($"Site Map Job Done At : {DateTime.Now}");
} }
} }

View File

@ -1,23 +1,8 @@
namespace Netina.Domain.CommandQueries.Commands; namespace Netina.Domain.CommandQueries.Commands;
public sealed record CreateBrandCommand(string PersianName, public sealed record CreateBrandCommand(string PersianName,string EnglishName, string Description , bool HasSpecialPage , string PageUrl, List<StorageFileSDto> Files) : IRequest<Guid>;
string EnglishName,
string Description ,
bool HasSpecialPage ,
string PageUrl,
List<StorageFileSDto> Files,
Dictionary<string, string> Faqs,
Dictionary<string, string> MetaTags) : IRequest<Guid>;
public sealed record UpdateBrandCommand(Guid Id, public sealed record UpdateBrandCommand(Guid Id,string PersianName, string EnglishName, string Description, bool HasSpecialPage, string PageUrl, List<StorageFileSDto> Files) : IRequest<bool>;
string PersianName,
string EnglishName,
string Description,
bool HasSpecialPage,
string PageUrl,
List<StorageFileSDto> Files,
Dictionary<string, string> Faqs,
Dictionary<string, string> MetaTags) : IRequest<bool>;
public sealed record DeleteBrandCommand(Guid Id) : IRequest<bool>; public sealed record DeleteBrandCommand(Guid Id) : IRequest<bool>;

View File

@ -1,27 +0,0 @@
namespace Netina.Domain.CommandQueries.Commands;
public sealed record CreateCommentCommand(
string Title,
string Content,
float Rate,
bool IsBuyer,
bool IsAdmin,
Guid? ParentId,
Guid? BlogId = null,
Guid? ProductId = null,
Guid? UserId = null) : IRequest<Guid>;
public sealed record UpdateCommentCommand(
Guid Id,
string Title,
string Content,
float Rate,
bool IsBuyer,
bool IsAdmin,
Guid? ParentId,
Guid? BlogId = null,
Guid? ProductId = null,
Guid? UserId = null) : IRequest<Guid>;
public sealed record ConfirmCommentCommand(Guid Id) : IRequest<Guid>;
public sealed record DeleteCommentCommand(Guid Id) : IRequest<Guid>;

View File

@ -21,8 +21,7 @@ bool IsForInvitation,
bool IsSpecialOffer, bool IsSpecialOffer,
bool IsForFirstPurchase, bool IsForFirstPurchase,
Guid ProductId, Guid ProductId,
Guid CategoryId, Guid CategoryId) : IRequest<DiscountLDto>;
Guid BrandId) : IRequest<DiscountLDto>;
public sealed record UpdateDiscountCommand( public sealed record UpdateDiscountCommand(
Guid Id, Guid Id,
@ -47,11 +46,9 @@ public sealed record UpdateDiscountCommand(
bool IsSpecialOffer, bool IsSpecialOffer,
bool IsForFirstPurchase, bool IsForFirstPurchase,
Guid ProductId, Guid ProductId,
Guid CategoryId, Guid CategoryId) : IRequest<bool>;
Guid BrandId) : IRequest<bool>;
public sealed record DeleteDiscountCommand(Guid Id) : IRequest<bool>; public sealed record DeleteDiscountCommand(Guid Id) : IRequest<bool>;
public sealed record CalculateOrderDiscountCommand(string DiscountCode, Order Order) : IRequest<double>; public sealed record CalculateOrderDiscountCommand(string DiscountCode, Order Order) : IRequest<double>;
public sealed record CheckUserDiscountFirstUseCommand(string DiscountCode) : IRequest<bool>;

View File

@ -1,15 +0,0 @@
namespace Netina.Domain.CommandQueries.Commands;
public record CreateFaqCommand(
Dictionary<string, string> Faqs,
string Slug,
string Title) : IRequest<bool>;
public record DeleteFaqCommand(Guid Id) : IRequest<bool>;
public record UpdateFaqCommand(
Guid Id,
Dictionary<string, string> Faqs,
string Slug,
string Title) : IRequest<bool>;

View File

@ -6,7 +6,7 @@ public sealed record CheckOrderBagCommand(List<CheckOrderBagRequestItem> OrderBa
public sealed record AddToOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>; public sealed record AddToOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;
public sealed record RemoveFromOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>; public sealed record RemoveFromOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;
public sealed record SubmitDiscountActionCommand(Guid OrderId,string? DiscountCode) : IRequest<OrderSDto>; public sealed record SubmitDiscountCommand(Guid OrderId,string DiscountCode) : IRequest<OrderSDto>;
public sealed record SubmitOrderDeliveryCommand(Guid AddressId, Guid OrderId, Guid ShippingId) : IRequest<OrderSDto>; public sealed record SubmitOrderDeliveryCommand(Guid AddressId, Guid OrderId, Guid ShippingId) : IRequest<OrderSDto>;
public sealed record SubmitOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>; public sealed record SubmitOrderBagCommand(List<OrderBagRequestDto> RequestDtos) : IRequest<OrderSDto>;

View File

@ -4,7 +4,6 @@ public sealed record CreateBaseOrderCommand(Guid UserId) : IRequest<Order>;
public sealed record CalculateOrderCommand(Guid OrderId , bool NamoosiCalculate = false) : IRequest<Order>; public sealed record CalculateOrderCommand(Guid OrderId , bool NamoosiCalculate = false) : IRequest<Order>;
public sealed record ConfirmOrderStepCommand(Guid OrderId , OrderStatus NextOrderStatus,string? TrackingCode) : IRequest<bool>; public sealed record ConfirmOrderStepCommand(Guid OrderId , OrderStatus NextOrderStatus,string? TrackingCode) : IRequest<bool>;
public sealed record CancelOrderStepCommand(Guid OrderId) : IRequest<bool>;
public sealed record GetOrderInvoiceCommand(Guid OrderId) : IRequest<byte[]>; public sealed record GetOrderInvoiceCommand(Guid OrderId) : IRequest<byte[]>;
public sealed record DeleteOrderCommand(Guid OrderId) : IRequest<bool>; public sealed record DeleteOrderCommand(Guid OrderId) : IRequest<bool>;

View File

@ -5,9 +5,7 @@ public sealed record CreateProductCategoryCommand(
string Description, string Description,
bool IsMain, bool IsMain,
Guid ParentId, Guid ParentId,
List<StorageFileSDto> Files, List<StorageFileSDto> Files) : IRequest<Guid>;
Dictionary<string, string> Faqs,
Dictionary<string, string> MetaTags) : IRequest<Guid>;
public sealed record UpdateProductCategoryCommand( public sealed record UpdateProductCategoryCommand(
Guid Id, Guid Id,
@ -15,8 +13,6 @@ public sealed record UpdateProductCategoryCommand(
string Description, string Description,
bool IsMain, bool IsMain,
Guid ParentId, Guid ParentId,
List<StorageFileSDto> Files, List<StorageFileSDto> Files) : IRequest<bool>;
Dictionary<string, string> Faqs,
Dictionary<string, string> MetaTags) : IRequest<bool>;
public sealed record DeleteProductCategoryCommand(Guid Id) : IRequest<bool>; public sealed record DeleteProductCategoryCommand(Guid Id) : IRequest<bool>;

View File

@ -18,9 +18,7 @@ public sealed record CreateProductCommand(
Guid CategoryId, Guid CategoryId,
DiscountSDto SpecialOffer, DiscountSDto SpecialOffer,
List<SpecificationSDto> Specifications, List<SpecificationSDto> Specifications,
List<StorageFileSDto> Files, List<StorageFileSDto> Files):IRequest<ProductLDto>;
Dictionary<string, string> Faqs,
Dictionary<string, string> MetaTags) : IRequest<ProductLDto>;
public sealed record UpdateProductCommand( public sealed record UpdateProductCommand(
Guid Id, Guid Id,
@ -41,14 +39,10 @@ public sealed record UpdateProductCommand(
Guid CategoryId, Guid CategoryId,
DiscountSDto SpecialOffer, DiscountSDto SpecialOffer,
List<SpecificationSDto> Specifications, List<SpecificationSDto> Specifications,
List<StorageFileSDto> Files, List<StorageFileSDto> Files) : IRequest<bool>;
Dictionary<string, string> Faqs,
Dictionary<string, string> MetaTags) : IRequest<bool>;
public sealed record ChangeProductDisplayedCommand(Guid Id,bool BeDisplayed) : IRequest<bool>; public sealed record ChangeProductDisplayedCommand(Guid Id,bool BeDisplayed) : IRequest<bool>;
public sealed record ChangeProductCostCommand(Guid Id, double Cost) : IRequest<bool>;
public sealed record DeleteProductCommand(Guid Id) : IRequest<bool>; public sealed record DeleteProductCommand(Guid Id) : IRequest<bool>;
public sealed record CalculateProductDiscountCommand(object Product) : IRequest<bool>; public sealed record CalculateProductDiscountCommand(object Product) : IRequest<bool>;

View File

@ -0,0 +1,6 @@
namespace Netina.Domain.CommandQueries.Commands;
public sealed record CreateReviewCommand(string Title, string Comment, float Rate, bool IsBuyer, Guid ProductId, Guid UserId) : IRequest<ReviewSDto>;
public sealed record UpdateReviewCommand(Guid Id,string Title, string Comment, float Rate, bool IsBuyer, Guid ProductId, Guid UserId): IRequest<bool>;
public sealed record ConfirmReviewCommand(Guid Id) : IRequest<bool>;
public sealed record DeleteReviewCommand(Guid Id) : IRequest<bool>;

View File

@ -1,33 +0,0 @@
namespace Netina.Domain.CommandQueries.Commands;
public sealed record CreateSubProductCommand(
Guid ParentId,
ProductDiversity Diversity,
string DiversityValue,
string DiversitySecondaryValue,
string DiversityDescription,
string PersianName,
double Cost,
double PackingCost,
int Stock,
bool HasExpressDelivery,
int MaxOrderCount,
List<StorageFileSDto> Files) : IRequest<Guid>;
public sealed record UpdateSubProductCommand(
Guid Id,
Guid ParentId,
ProductDiversity Diversity,
string DiversityValue,
string DiversitySecondaryValue,
string DiversityDescription,
string PersianName,
double Cost,
double PackingCost,
int Stock,
bool HasExpressDelivery,
int MaxOrderCount,
List<StorageFileSDto> Files) : IRequest<Guid>;
public sealed record DeleteSubProductCommand(Guid Id) : IRequest<bool>;

View File

@ -1,4 +0,0 @@
namespace Netina.Domain.CommandQueries.Queries;
public record GetCommentsQuery(int Page = 0,int Count = Refers.SizeM ,Guid? ProductId = null, Guid? BlogId = null) : IRequest<List<CommentSDto>>;
public record GetCommentQuery(Guid Id) : IRequest<CommentLDto>;

View File

@ -1,3 +0,0 @@
namespace Netina.Domain.CommandQueries.Queries;
public record GetCustomersQuery(int Page = 0, int Count = Refers.SizeM) : IRequest<List<CustomerSDto>>;

View File

@ -1,4 +0,0 @@
namespace Netina.Domain.CommandQueries.Queries;
public record GetFaqQuery(Guid? Id,string? Slug) : IRequest<BaseFaq>;
public record GetFaqsQuery(int Page , int Count = 0) : IRequest<List<BaseFaq>>;

View File

@ -4,4 +4,4 @@ public sealed record GetOrderLDtoQuery(Guid Id) : IRequest<OrderLDto>;
public sealed record GetUserOrdersQuery(Guid CustomerId = default) : IRequest<List<OrderSDto>>; public sealed record GetUserOrdersQuery(Guid CustomerId = default) : IRequest<List<OrderSDto>>;
public sealed record GetOrderQuery(Guid Id) : IRequest<Order>; public sealed record GetOrderQuery(Guid Id) : IRequest<Order>;
public sealed record GetOrdersQuery(OrderQueryDateFilter? DateFilter, OrderStatus? OrderStatus,long? SelectedDate,string? FactorCode,bool OrderBags, int Page = 0) : IRequest<List<OrderSDto>>; public sealed record GetOrdersQuery(OrderQueryDateFilter? DateFilter, OrderStatus? OrderStatus,long? SelectedDate,string? FactorCode, int Page = 0) : IRequest<List<OrderSDto>>;

View File

@ -7,7 +7,7 @@ public sealed record GetProductsQuery(
bool? IsActive, bool? IsActive,
bool? SpecialOffer, bool? SpecialOffer,
int Page = 0 , int Page = 0 ,
string? ProductName = null, string? ProductName = default,
QuerySortBy SortBy = QuerySortBy.None , QuerySortBy SortBy = QuerySortBy.None ,
Guid CategoryId = default , Guid CategoryId = default ,
double MinPrice = -1 , double MinPrice = -1 ,

View File

@ -0,0 +1,4 @@
namespace Netina.Domain.CommandQueries.Queries;
public record GetReviewsQuery(int Page = 0) : IRequest<List<ReviewSDto>>;
public record GetReviewQuery(Guid Id) : IRequest<ReviewLDto>;

Some files were not shown because too many files have changed in this diff Show More