feat: integrate PYMS payment gateway, add blog/sitepage/image services, local file manager
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m44s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m44s
Payment Gateway: - Add PYMSPaymentService: IPaymentGatewayService via gRPC to PYMS microservice - Add ZarinPalPaymentService: direct ZarinPal integration (backup) - Register 'pyms' payment provider in DI ConfigureServices - Add PYMS proto files (pyms_transaction.proto, pyms_public_messages.proto) - Fix VerifyDiscountWalletCharge: pass 'OK' as status instead of Authority - Update appsettings: PaymentProvider=pyms, sandbox mode, merchant ID Blog System: - Add BlogCategory, BlogPost, BlogPostImage entities and CQRS - Add proto files and gRPC services for blog management - Add Mapster profiles for blog responses Content Management: - Add SitePage entity and CQRS for static pages - Add proto and gRPC service for site pages Image/File Management: - Add LocalFileManager with disk storage + base64 serving + FMS fallback - Add ImagePathResolverInterceptor for gRPC responses - Add ImageResolverService for explicit image resolution - Add UploadsController for public file serving with FMS fallback - Add PaymentCallbackController for discount order payment callbacks Database: - Add blog and content entity migrations - Remove ImagePath MaxLength constraints - Remove old FileManagementService (replaced by LocalFileManager)
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
using CMSMicroservice.Protobuf.Protos.BlogCategory;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.BlogCategoryCQ.Commands.CreateBlogCategory;
|
||||
using CMSMicroservice.Application.BlogCategoryCQ.Commands.UpdateBlogCategory;
|
||||
using CMSMicroservice.Application.BlogCategoryCQ.Commands.DeleteBlogCategory;
|
||||
using CMSMicroservice.Application.BlogCategoryCQ.Queries.GetBlogCategory;
|
||||
using CMSMicroservice.Application.BlogCategoryCQ.Queries.GetAllBlogCategories;
|
||||
using CMSMicroservice.Application.BlogCategoryCQ.Queries.GetActiveBlogCategories;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Grpc.Core;
|
||||
using Mapster;
|
||||
using MediatR;
|
||||
using AppModels = CMSMicroservice.Application.Common.Models;
|
||||
using ProtoMetaData = CMSMicroservice.Protobuf.Protos.MetaData;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
public class BlogCategoryService : BlogCategoryContract.BlogCategoryContractBase
|
||||
{
|
||||
private readonly ISender _sender;
|
||||
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
|
||||
|
||||
public BlogCategoryService(ISender sender, IDispatchRequestToCQRS dispatchRequestToCQRS)
|
||||
{
|
||||
_sender = sender;
|
||||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||
}
|
||||
|
||||
public override async Task<CreateBlogCategoryResponse> CreateBlogCategory(CreateBlogCategoryRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<CreateBlogCategoryRequest, CreateBlogCategoryCommand, CreateBlogCategoryResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<Empty> UpdateBlogCategory(UpdateBlogCategoryRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<UpdateBlogCategoryRequest, UpdateBlogCategoryCommand>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<Empty> DeleteBlogCategory(DeleteBlogCategoryRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<DeleteBlogCategoryRequest, DeleteBlogCategoryCommand>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetBlogCategoryResponse> GetBlogCategory(GetBlogCategoryRequest request, ServerCallContext context)
|
||||
{
|
||||
var query = new GetBlogCategoryQuery { Id = request.Id };
|
||||
var result = await _sender.Send(query, context.CancellationToken);
|
||||
return MapCategoryToResponse(result);
|
||||
}
|
||||
|
||||
public override async Task<GetAllBlogCategoriesResponse> GetAllBlogCategories(GetAllBlogCategoriesRequest request, ServerCallContext context)
|
||||
{
|
||||
var query = new GetAllBlogCategoriesQuery
|
||||
{
|
||||
PageNumber = request.PaginationState?.PageNumber ?? 1,
|
||||
PageSize = request.PaginationState?.PageSize ?? 20,
|
||||
SearchTerm = request.SortBy
|
||||
};
|
||||
|
||||
var result = await _sender.Send(query, context.CancellationToken);
|
||||
var response = new GetAllBlogCategoriesResponse
|
||||
{
|
||||
MetaData = result.MetaData.Adapt<ProtoMetaData>()
|
||||
};
|
||||
|
||||
foreach (var item in result.Models)
|
||||
response.Models.Add(MapToListItem(item));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<GetActiveBlogCategoriesResponse> GetActiveBlogCategories(GetActiveBlogCategoriesRequest request, ServerCallContext context)
|
||||
{
|
||||
var query = new GetActiveBlogCategoriesQuery();
|
||||
var result = await _sender.Send(query, context.CancellationToken);
|
||||
|
||||
var response = new GetActiveBlogCategoriesResponse();
|
||||
foreach (var item in result)
|
||||
response.Categories.Add(MapToListItem(item));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// ── Private Mapping Helpers ──
|
||||
|
||||
private static GetBlogCategoryResponse MapCategoryToResponse(BlogCategoryDto dto)
|
||||
{
|
||||
return new GetBlogCategoryResponse
|
||||
{
|
||||
Id = dto.Id,
|
||||
Title = dto.Title ?? string.Empty,
|
||||
Slug = dto.Slug ?? string.Empty,
|
||||
Description = dto.Description,
|
||||
IconName = dto.IconName,
|
||||
SortOrder = dto.SortOrder,
|
||||
IsActive = dto.IsActive,
|
||||
PostCount = dto.PostCount,
|
||||
Created = dto.Created != default ? Timestamp.FromDateTime(DateTime.SpecifyKind(dto.Created, DateTimeKind.Utc)) : null
|
||||
};
|
||||
}
|
||||
|
||||
private static BlogCategoryListItem MapToListItem(BlogCategoryDto dto)
|
||||
{
|
||||
return new BlogCategoryListItem
|
||||
{
|
||||
Id = dto.Id,
|
||||
Title = dto.Title ?? string.Empty,
|
||||
Slug = dto.Slug ?? string.Empty,
|
||||
Description = dto.Description,
|
||||
IconName = dto.IconName,
|
||||
SortOrder = dto.SortOrder,
|
||||
IsActive = dto.IsActive,
|
||||
PostCount = dto.PostCount
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user