Files
pos-system/services/merchant-service-net/src/MerchantService.API/Application/Queries/Admin/GetMerchantDetailQuery.cs
Ho Ngoc Hai 90debb3e94 fix(superadmin): resolve merchant admin query EF Core translation errors
- Fix IsDeleted/CreatedAt/BusinessName private field access in LINQ queries
  using EF.Property<T>() instead of public computed properties (which are
  Ignored in EF config due to DDD pattern)
- Fix Shop.MerchantId private field in GroupBy shop count query
- Split merchant list query into 2 steps (fetch + batch shop counts)
  to avoid untranslatable subquery in Join+Select
- Fix BFF SuperAdminController: remove duplicate auth header setting
  (AuthForwardingHandler already reads bff_session cookie)
- Fix frontend DTO field names to match API response (ShopsCount, Type)
- Fix frontend response format handling for direct {items} without {data} wrapper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:39:26 +07:00

80 lines
2.8 KiB
C#

// EN: Query to get merchant details for admin.
// VI: Query để lấy chi tiết merchant cho admin.
using MediatR;
using Microsoft.EntityFrameworkCore;
using MerchantService.Domain.Exceptions;
using MerchantService.Infrastructure;
namespace MerchantService.API.Application.Queries.Admin;
/// <summary>
/// EN: Query to get detailed merchant information (Admin only).
/// VI: Query để lấy thông tin chi tiết merchant (chỉ Admin).
/// </summary>
public record GetMerchantDetailQuery(Guid MerchantId) : IRequest<AdminMerchantDetailDto>;
/// <summary>
/// EN: Handler for GetMerchantDetailQuery.
/// VI: Handler cho GetMerchantDetailQuery.
/// </summary>
public class GetMerchantDetailQueryHandler : IRequestHandler<GetMerchantDetailQuery, AdminMerchantDetailDto>
{
private readonly MerchantServiceContext _context;
public GetMerchantDetailQueryHandler(MerchantServiceContext context)
{
_context = context;
}
public async Task<AdminMerchantDetailDto> Handle(
GetMerchantDetailQuery request,
CancellationToken cancellationToken)
{
var merchant = await _context.Merchants
.AsNoTracking()
.Where(m => m.Id == request.MerchantId && !EF.Property<bool>(m, "_isDeleted"))
.FirstOrDefaultAsync(cancellationToken)
?? throw new DomainException($"Merchant {request.MerchantId} not found");
var shopsCount = await _context.Shops
.CountAsync(s => s.MerchantId == request.MerchantId && !EF.Property<bool>(s, "_isDeleted"), cancellationToken);
var staffCount = await _context.MerchantStaff
.CountAsync(s => s.MerchantId == request.MerchantId, cancellationToken);
var businessInfo = merchant.BusinessInfo != null
? new AdminBusinessInfoDto(
merchant.BusinessInfo.TaxId,
merchant.BusinessInfo.BusinessLicenseNumber,
merchant.BusinessInfo.CompanyRegistrationNumber,
null,
null,
null)
: null;
var settlementConfig = merchant.SettlementConfig != null
? new AdminSettlementConfigDto(
merchant.SettlementConfig.CommissionRate,
merchant.SettlementConfig.SettlementCycleId.ToString(),
merchant.SettlementConfig.BankAccount?.ToString())
: null;
return new AdminMerchantDetailDto(
merchant.Id,
merchant.UserId,
merchant.BusinessName,
merchant.Type.Name,
merchant.Status.Name,
merchant.VerificationStatus.Name,
businessInfo,
settlementConfig,
shopsCount,
staffCount,
merchant.CreatedAt,
merchant.UpdatedAt,
merchant.VerifiedAt,
merchant.VerifiedBy);
}
}