feat: Implement user permission checks and manual payment functionalities
- Added CheckUserPermissionQuery and CheckUserPermissionQueryHandler for permission validation. - Introduced GetUserRolesQuery and GetUserRolesQueryHandler to retrieve user roles. - Created IPermissionService interface and its implementation in PermissionService. - Defined permission and role constants in PermissionDefinitions. - Developed SetDefaultVatPercentageCommand and its handler for VAT configuration. - Implemented GetCurrentVatPercentageQuery and handler to fetch current VAT settings. - Added manual payment commands: CreateManualPayment, ApproveManualPayment, and RejectManualPayment with respective handlers and validators. - Created GetManualPaymentsQuery and handler for retrieving manual payment records. - Integrated gRPC services for manual payments with appropriate permission checks. - Established Protobuf definitions for manual payment operations and metadata.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
using MediatR;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ApproveManualPayment;
|
||||
|
||||
public class ApproveManualPaymentCommand : IRequest<bool>
|
||||
{
|
||||
public long ManualPaymentId { get; set; }
|
||||
public string? ApprovalNote { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
using BackOffice.BFF.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Protobuf.Protos.ManualPayment;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ApproveManualPayment;
|
||||
|
||||
public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualPaymentCommand, bool>
|
||||
{
|
||||
private readonly IApplicationContractContext _context;
|
||||
private readonly ILogger<ApproveManualPaymentCommandHandler> _logger;
|
||||
|
||||
public ApproveManualPaymentCommandHandler(
|
||||
IApplicationContractContext context,
|
||||
ILogger<ApproveManualPaymentCommandHandler> logger)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> Handle(ApproveManualPaymentCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Approving manual payment via BFF. Id: {Id}", request.ManualPaymentId);
|
||||
|
||||
var grpcRequest = new ApproveManualPaymentRequest
|
||||
{
|
||||
ManualPaymentId = request.ManualPaymentId
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.ApprovalNote))
|
||||
{
|
||||
grpcRequest.ApprovalNote = new StringValue { Value = request.ApprovalNote };
|
||||
}
|
||||
|
||||
await _context.ManualPayments.ApproveManualPaymentAsync(grpcRequest, cancellationToken: cancellationToken);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.ApproveManualPayment;
|
||||
|
||||
public class ApproveManualPaymentCommandValidator : AbstractValidator<ApproveManualPaymentCommand>
|
||||
{
|
||||
public ApproveManualPaymentCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.ManualPaymentId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه پرداخت دستی نامعتبر است.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using MediatR;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.CreateManualPayment;
|
||||
|
||||
public class CreateManualPaymentCommand : IRequest<CreateManualPaymentResponseDto>
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long Amount { get; set; }
|
||||
public int Type { get; set; }
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public string? ReferenceNumber { get; set; }
|
||||
}
|
||||
|
||||
public class CreateManualPaymentResponseDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using BackOffice.BFF.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Protobuf.Protos.ManualPayment;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.CreateManualPayment;
|
||||
|
||||
public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPaymentCommand, CreateManualPaymentResponseDto>
|
||||
{
|
||||
private readonly IApplicationContractContext _context;
|
||||
private readonly ILogger<CreateManualPaymentCommandHandler> _logger;
|
||||
|
||||
public CreateManualPaymentCommandHandler(
|
||||
IApplicationContractContext context,
|
||||
ILogger<CreateManualPaymentCommandHandler> logger)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<CreateManualPaymentResponseDto> Handle(CreateManualPaymentCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Creating manual payment via BFF for UserId {UserId}, Amount {Amount}, Type {Type}",
|
||||
request.UserId,
|
||||
request.Amount,
|
||||
request.Type);
|
||||
|
||||
var grpcRequest = new CreateManualPaymentRequest
|
||||
{
|
||||
UserId = request.UserId,
|
||||
Amount = request.Amount,
|
||||
Type = (ManualPaymentType)request.Type,
|
||||
Description = request.Description
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.ReferenceNumber))
|
||||
{
|
||||
grpcRequest.ReferenceNumber = new StringValue { Value = request.ReferenceNumber };
|
||||
}
|
||||
|
||||
var response = await _context.ManualPayments.CreateManualPaymentAsync(grpcRequest, cancellationToken: cancellationToken);
|
||||
|
||||
return new CreateManualPaymentResponseDto
|
||||
{
|
||||
Id = response.Id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.CreateManualPayment;
|
||||
|
||||
public class CreateManualPaymentCommandValidator : AbstractValidator<CreateManualPaymentCommand>
|
||||
{
|
||||
public CreateManualPaymentCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.UserId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر باید بزرگتر از صفر باشد.");
|
||||
|
||||
RuleFor(x => x.Amount)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("مبلغ باید بزرگتر از صفر باشد.");
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.NotEmpty()
|
||||
.WithMessage("توضیحات الزامی است.");
|
||||
|
||||
RuleFor(x => x.Type)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("نوع پرداخت دستی نامعتبر است.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using MediatR;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.RejectManualPayment;
|
||||
|
||||
public class RejectManualPaymentCommand : IRequest<bool>
|
||||
{
|
||||
public long ManualPaymentId { get; set; }
|
||||
public string RejectionReason { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using BackOffice.BFF.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Protobuf.Protos.ManualPayment;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.RejectManualPayment;
|
||||
|
||||
public class RejectManualPaymentCommandHandler : IRequestHandler<RejectManualPaymentCommand, bool>
|
||||
{
|
||||
private readonly IApplicationContractContext _context;
|
||||
private readonly ILogger<RejectManualPaymentCommandHandler> _logger;
|
||||
|
||||
public RejectManualPaymentCommandHandler(
|
||||
IApplicationContractContext context,
|
||||
ILogger<RejectManualPaymentCommandHandler> logger)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> Handle(RejectManualPaymentCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Rejecting manual payment via BFF. Id: {Id}", request.ManualPaymentId);
|
||||
|
||||
var grpcRequest = new RejectManualPaymentRequest
|
||||
{
|
||||
ManualPaymentId = request.ManualPaymentId,
|
||||
RejectionReason = request.RejectionReason
|
||||
};
|
||||
|
||||
await _context.ManualPayments.RejectManualPaymentAsync(grpcRequest, cancellationToken: cancellationToken);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Commands.RejectManualPayment;
|
||||
|
||||
public class RejectManualPaymentCommandValidator : AbstractValidator<RejectManualPaymentCommand>
|
||||
{
|
||||
public RejectManualPaymentCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.ManualPaymentId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه پرداخت دستی نامعتبر است.");
|
||||
|
||||
RuleFor(x => x.RejectionReason)
|
||||
.NotEmpty()
|
||||
.WithMessage("دلیل رد الزامی است.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using MediatR;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Queries.GetManualPayments;
|
||||
|
||||
public class GetManualPaymentsQuery : IRequest<GetManualPaymentsResponseDto>
|
||||
{
|
||||
public int PageNumber { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 10;
|
||||
public long? UserId { get; set; }
|
||||
public int? Status { get; set; }
|
||||
public int? Type { get; set; }
|
||||
public long? RequestedBy { get; set; }
|
||||
public bool OrderByDescending { get; set; } = true;
|
||||
public string? ReferenceNumber { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using BackOffice.BFF.Application.Common.Interfaces;
|
||||
using BackOffice.BFF.Application.Common.Models;
|
||||
using CMSMicroservice.Protobuf.Protos.ManualPayment;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Queries.GetManualPayments;
|
||||
|
||||
public class GetManualPaymentsQueryHandler : IRequestHandler<GetManualPaymentsQuery, GetManualPaymentsResponseDto>
|
||||
{
|
||||
private readonly IApplicationContractContext _context;
|
||||
private readonly ILogger<GetManualPaymentsQueryHandler> _logger;
|
||||
|
||||
public GetManualPaymentsQueryHandler(
|
||||
IApplicationContractContext context,
|
||||
ILogger<GetManualPaymentsQueryHandler> logger)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<GetManualPaymentsResponseDto> Handle(GetManualPaymentsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Getting manual payments via BFF. Page: {Page}, PageSize: {PageSize}, Status: {Status}, Type: {Type}",
|
||||
request.PageNumber,
|
||||
request.PageSize,
|
||||
request.Status,
|
||||
request.Type);
|
||||
|
||||
var grpcRequest = new GetAllManualPaymentsRequest
|
||||
{
|
||||
PageNumber = request.PageNumber,
|
||||
PageSize = request.PageSize
|
||||
};
|
||||
|
||||
if (request.UserId.HasValue)
|
||||
{
|
||||
grpcRequest.UserId = new Int64Value { Value = request.UserId.Value };
|
||||
}
|
||||
|
||||
if (request.Status.HasValue)
|
||||
{
|
||||
grpcRequest.Status = new Int32Value { Value = request.Status.Value };
|
||||
}
|
||||
|
||||
if (request.Type.HasValue)
|
||||
{
|
||||
grpcRequest.Type = new Int32Value { Value = request.Type.Value };
|
||||
}
|
||||
|
||||
if (request.RequestedBy.HasValue)
|
||||
{
|
||||
grpcRequest.RequestedBy = new Int64Value { Value = request.RequestedBy.Value };
|
||||
}
|
||||
|
||||
grpcRequest.OrderByDescending = new BoolValue { Value = request.OrderByDescending };
|
||||
|
||||
var response = await _context.ManualPayments.GetAllManualPaymentsAsync(grpcRequest, cancellationToken: cancellationToken);
|
||||
|
||||
var meta = response.MetaData;
|
||||
|
||||
var models = response.Models?
|
||||
.Select(m => new ManualPaymentModel
|
||||
{
|
||||
Id = m.Id,
|
||||
UserId = m.UserId,
|
||||
UserFullName = m.UserFullName,
|
||||
UserMobile = m.UserMobile,
|
||||
Amount = m.Amount,
|
||||
Type = (int)m.Type,
|
||||
TypeDisplay = m.TypeDisplay,
|
||||
Description = m.Description,
|
||||
ReferenceNumber = m.ReferenceNumber,
|
||||
Status = (int)m.Status,
|
||||
StatusDisplay = m.StatusDisplay,
|
||||
RequestedBy = m.RequestedBy,
|
||||
RequestedByName = m.RequestedByName,
|
||||
ApprovedBy = m.ApprovedBy?.Value,
|
||||
ApprovedByName = m.ApprovedByName,
|
||||
ApprovedAt = m.ApprovedAt?.ToDateTime(),
|
||||
RejectionReason = m.RejectionReason,
|
||||
TransactionId = m.TransactionId?.Value,
|
||||
Created = m.Created.ToDateTime()
|
||||
})
|
||||
.ToList()
|
||||
?? new List<ManualPaymentModel>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.ReferenceNumber))
|
||||
{
|
||||
models = models
|
||||
.Where(m => !string.IsNullOrWhiteSpace(m.ReferenceNumber) &&
|
||||
m.ReferenceNumber.Contains(request.ReferenceNumber!, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
var result = new GetManualPaymentsResponseDto
|
||||
{
|
||||
MetaData = new MetaData
|
||||
{
|
||||
CurrentPage = meta.CurrentPage,
|
||||
TotalPage = meta.TotalPage,
|
||||
PageSize = meta.PageSize,
|
||||
TotalCount = meta.TotalCount,
|
||||
HasPrevious = meta.HasPrevious,
|
||||
HasNext = meta.HasNext
|
||||
},
|
||||
Models = models
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using BackOffice.BFF.Application.Common.Models;
|
||||
|
||||
namespace BackOffice.BFF.Application.ManualPaymentCQ.Queries.GetManualPayments;
|
||||
|
||||
public class GetManualPaymentsResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; } = new();
|
||||
public List<ManualPaymentModel>? Models { get; set; }
|
||||
}
|
||||
|
||||
public class ManualPaymentModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string UserFullName { get; set; } = string.Empty;
|
||||
public string UserMobile { get; set; } = string.Empty;
|
||||
public long Amount { get; set; }
|
||||
public int Type { get; set; }
|
||||
public string TypeDisplay { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public string? ReferenceNumber { get; set; }
|
||||
public int Status { get; set; }
|
||||
public string StatusDisplay { get; set; } = string.Empty;
|
||||
public long RequestedBy { get; set; }
|
||||
public string RequestedByName { get; set; } = string.Empty;
|
||||
public long? ApprovedBy { get; set; }
|
||||
public string? ApprovedByName { get; set; }
|
||||
public DateTime? ApprovedAt { get; set; }
|
||||
public string? RejectionReason { get; set; }
|
||||
public long? TransactionId { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user