From bcadf2b8e4248de10d43ce0dc01753f503a00176 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Thu, 15 Jan 2026 22:17:55 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20B=E1=BB=95=20sung=20c=C3=A1c=20ch?= =?UTF-8?q?=E1=BB=A9c=20n=C4=83ng=20qu=E1=BA=A3n=20tr=E1=BB=8B=20vi=C3=AAn?= =?UTF-8?q?=20=C4=91=E1=BB=83=20qu=E1=BA=A3n=20l=C3=BD=20v=C3=AD=20v=C3=A0?= =?UTF-8?q?=20t=C3=A0i=20kho=E1=BA=A3n=20=C4=91i=E1=BB=83m,=20bao=20g?= =?UTF-8?q?=E1=BB=93m=20c=C3=A1c=20l=E1=BB=87nh=20=C4=91i=E1=BB=81u=20ch?= =?UTF-8?q?=E1=BB=89nh=20v=C3=A0=20truy=20v=E1=BA=A5n.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deployments/local/docker-compose.yml | 2 +- .../Commands/AdminPointsCommandHandlers.cs | 99 ++++++++ .../Commands/AdminWalletCommandHandlers.cs | 145 ++++++++++++ .../Queries/AdminPointsQueryHandlers.cs | 181 +++++++++++++++ .../Queries/AdminWalletQueryHandlers.cs | 211 ++++++++++++++++++ .../IPointAccountRepository.cs | 6 + .../WalletAggregate/IWalletRepository.cs | 6 + .../Repositories/PointAccountRepository.cs | 6 + .../Repositories/WalletRepository.cs | 8 + 9 files changed, 663 insertions(+), 1 deletion(-) create mode 100644 services/wallet-service-net/src/WalletService.API/Application/Commands/AdminPointsCommandHandlers.cs create mode 100644 services/wallet-service-net/src/WalletService.API/Application/Commands/AdminWalletCommandHandlers.cs create mode 100644 services/wallet-service-net/src/WalletService.API/Application/Queries/AdminPointsQueryHandlers.cs create mode 100644 services/wallet-service-net/src/WalletService.API/Application/Queries/AdminWalletQueryHandlers.cs diff --git a/deployments/local/docker-compose.yml b/deployments/local/docker-compose.yml index aad24f4a..f306bbd3 100644 --- a/deployments/local/docker-compose.yml +++ b/deployments/local/docker-compose.yml @@ -301,7 +301,7 @@ services: start_period: 40s labels: - "traefik.enable=true" - - "traefik.http.routers.wallet-service.rule=PathPrefix(`/api/v1/wallets`) || PathPrefix(`/api/v1/points`)" + - "traefik.http.routers.wallet-service.rule=PathPrefix(`/api/v1/wallets`) || PathPrefix(`/api/v1/points`) || PathPrefix(`/api/v1/admin/wallets`) || PathPrefix(`/api/v1/admin/points`)" - "traefik.http.routers.wallet-service.entrypoints=web" - "traefik.http.services.wallet-service.loadbalancer.server.port=8080" - "traefik.http.services.wallet-service.loadbalancer.healthcheck.path=/health/live" diff --git a/services/wallet-service-net/src/WalletService.API/Application/Commands/AdminPointsCommandHandlers.cs b/services/wallet-service-net/src/WalletService.API/Application/Commands/AdminPointsCommandHandlers.cs new file mode 100644 index 00000000..6b747d32 --- /dev/null +++ b/services/wallet-service-net/src/WalletService.API/Application/Commands/AdminPointsCommandHandlers.cs @@ -0,0 +1,99 @@ +namespace WalletService.API.Application.Commands; + +using MediatR; +using WalletService.Domain.AggregatesModel.PointAccountAggregate; +using WalletService.Domain.Exceptions; + +/// +/// EN: Handler for AdminAdjustPointsCommand. +/// VI: Handler cho AdminAdjustPointsCommand. +/// +public class AdminAdjustPointsCommandHandler : IRequestHandler +{ + private readonly IPointAccountRepository _pointAccountRepository; + private readonly ILogger _logger; + + public AdminAdjustPointsCommandHandler( + IPointAccountRepository pointAccountRepository, + ILogger logger) + { + _pointAccountRepository = pointAccountRepository; + _logger = logger; + } + + public async Task Handle( + AdminAdjustPointsCommand request, + CancellationToken cancellationToken) + { + var account = await _pointAccountRepository.GetByIdAsync(request.AccountId) + ?? throw new WalletDomainException($"Point account {request.AccountId} not found"); + + var previousPoints = account.AvailablePoints; + + // EN: Adjust points directly using domain method + // VI: Điều chỉnh điểm trực tiếp bằng phương thức domain + account.AdjustPoints(request.Points, $"Admin Adjustment: {request.Reason}"); + + _pointAccountRepository.Update(account); + await _pointAccountRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + + _logger.LogInformation( + "Point account {AccountId} adjusted by Admin {AdminId}. Points: {Points}. Reason: {Reason}", + request.AccountId, request.AdminId, request.Points, request.Reason); + + return new AdminAdjustPointsResult( + account.Id, + previousPoints, + request.Points, + account.AvailablePoints, + request.Reason, + DateTime.UtcNow); + } +} + +/// +/// EN: Handler for AdminGrantBonusCommand. +/// VI: Handler cho AdminGrantBonusCommand. +/// +public class AdminGrantBonusCommandHandler : IRequestHandler +{ + private readonly IPointAccountRepository _pointAccountRepository; + private readonly ILogger _logger; + + public AdminGrantBonusCommandHandler( + IPointAccountRepository pointAccountRepository, + ILogger logger) + { + _pointAccountRepository = pointAccountRepository; + _logger = logger; + } + + public async Task Handle( + AdminGrantBonusCommand request, + CancellationToken cancellationToken) + { + var account = await _pointAccountRepository.GetByIdAsync(request.AccountId) + ?? throw new WalletDomainException($"Point account {request.AccountId} not found"); + + var expiryMonths = request.ExpiryMonths ?? 12; + var expiresAt = DateTime.UtcNow.AddMonths(expiryMonths); + + // EN: Earn bonus points with expiry + // VI: Tích điểm thưởng với thời hạn + account.AddBonusPoints(request.Points, "AdminBonus", $"Admin Bonus: {request.Reason}", expiresAt); + + _pointAccountRepository.Update(account); + await _pointAccountRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + + _logger.LogInformation( + "Point account {AccountId} granted {Points} bonus points by Admin {AdminId}. Reason: {Reason}", + request.AccountId, request.Points, request.AdminId, request.Reason); + + return new AdminGrantBonusResult( + account.Id, + request.Points, + account.AvailablePoints, + expiresAt, + DateTime.UtcNow); + } +} diff --git a/services/wallet-service-net/src/WalletService.API/Application/Commands/AdminWalletCommandHandlers.cs b/services/wallet-service-net/src/WalletService.API/Application/Commands/AdminWalletCommandHandlers.cs new file mode 100644 index 00000000..67bc9628 --- /dev/null +++ b/services/wallet-service-net/src/WalletService.API/Application/Commands/AdminWalletCommandHandlers.cs @@ -0,0 +1,145 @@ +namespace WalletService.API.Application.Commands; + +using MediatR; +using WalletService.Domain.AggregatesModel.WalletAggregate; +using WalletService.Domain.Exceptions; + +/// +/// EN: Handler for AdminFreezeWalletCommand. +/// VI: Handler cho AdminFreezeWalletCommand. +/// +public class AdminFreezeWalletCommandHandler : IRequestHandler +{ + private readonly IWalletRepository _walletRepository; + private readonly ILogger _logger; + + public AdminFreezeWalletCommandHandler( + IWalletRepository walletRepository, + ILogger logger) + { + _walletRepository = walletRepository; + _logger = logger; + } + + public async Task Handle( + AdminFreezeWalletCommand request, + CancellationToken cancellationToken) + { + var wallet = await _walletRepository.GetByIdAsync(request.WalletId) + ?? throw new WalletDomainException($"Wallet {request.WalletId} not found"); + + wallet.Freeze(); + + _walletRepository.Update(wallet); + await _walletRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + + _logger.LogInformation( + "Wallet {WalletId} frozen by Admin {AdminId}. Reason: {Reason}", + request.WalletId, request.AdminId, request.Reason); + + return new AdminWalletActionResult( + wallet.Id, + wallet.Status.Name, + request.AdminId.ToString(), + DateTime.UtcNow); + } +} + +/// +/// EN: Handler for AdminUnfreezeWalletCommand. +/// VI: Handler cho AdminUnfreezeWalletCommand. +/// +public class AdminUnfreezeWalletCommandHandler : IRequestHandler +{ + private readonly IWalletRepository _walletRepository; + private readonly ILogger _logger; + + public AdminUnfreezeWalletCommandHandler( + IWalletRepository walletRepository, + ILogger logger) + { + _walletRepository = walletRepository; + _logger = logger; + } + + public async Task Handle( + AdminUnfreezeWalletCommand request, + CancellationToken cancellationToken) + { + var wallet = await _walletRepository.GetByIdAsync(request.WalletId) + ?? throw new WalletDomainException($"Wallet {request.WalletId} not found"); + + wallet.Unfreeze(); + + _walletRepository.Update(wallet); + await _walletRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + + _logger.LogInformation( + "Wallet {WalletId} unfrozen by Admin {AdminId}. Reason: {Reason}", + request.WalletId, request.AdminId, request.Reason); + + return new AdminWalletActionResult( + wallet.Id, + wallet.Status.Name, + request.AdminId.ToString(), + DateTime.UtcNow); + } +} + +/// +/// EN: Handler for AdminAdjustBalanceCommand. +/// VI: Handler cho AdminAdjustBalanceCommand. +/// +public class AdminAdjustBalanceCommandHandler : IRequestHandler +{ + private readonly IWalletRepository _walletRepository; + private readonly ILogger _logger; + + public AdminAdjustBalanceCommandHandler( + IWalletRepository walletRepository, + ILogger logger) + { + _walletRepository = walletRepository; + _logger = logger; + } + + public async Task Handle( + AdminAdjustBalanceCommand request, + CancellationToken cancellationToken) + { + var wallet = await _walletRepository.GetByIdAsync(request.WalletId) + ?? throw new WalletDomainException($"Wallet {request.WalletId} not found"); + + var currencyType = Domain.SeedWork.Enumeration.FromValue(request.CurrencyTypeId); + var previousBalance = wallet.GetBalance(currencyType); + + // EN: Positive amount = credit, negative = debit + // VI: Số dương = cộng, số âm = trừ + if (request.Amount > 0) + { + wallet.Deposit(request.Amount, currencyType, $"Admin Adjustment: {request.Reason}"); + } + else if (request.Amount < 0) + { + wallet.Withdraw(Math.Abs(request.Amount), currencyType, $"Admin Adjustment: {request.Reason}"); + } + + _walletRepository.Update(wallet); + await _walletRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + + var newBalance = wallet.GetBalance(currencyType); + + _logger.LogInformation( + "Wallet {WalletId} balance adjusted by Admin {AdminId}. Amount: {Amount} {Currency}. Reason: {Reason}", + request.WalletId, request.AdminId, request.Amount, currencyType.Name, request.Reason); + + return new AdminAdjustBalanceResult( + wallet.Id, + previousBalance, + request.Amount, + newBalance, + currencyType.Name, + request.Reason, + DateTime.UtcNow); + } +} diff --git a/services/wallet-service-net/src/WalletService.API/Application/Queries/AdminPointsQueryHandlers.cs b/services/wallet-service-net/src/WalletService.API/Application/Queries/AdminPointsQueryHandlers.cs new file mode 100644 index 00000000..2e0267e1 --- /dev/null +++ b/services/wallet-service-net/src/WalletService.API/Application/Queries/AdminPointsQueryHandlers.cs @@ -0,0 +1,181 @@ +namespace WalletService.API.Application.Queries; + +using MediatR; +using Microsoft.EntityFrameworkCore; +using WalletService.Domain.AggregatesModel.PointAccountAggregate; +using WalletService.Infrastructure; + +/// +/// EN: Handler for GetAllPointAccountsQuery (Admin). +/// VI: Handler cho GetAllPointAccountsQuery (Admin). +/// +public class GetAllPointAccountsQueryHandler : IRequestHandler +{ + private readonly WalletServiceContext _context; + + public GetAllPointAccountsQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task Handle( + GetAllPointAccountsQuery request, + CancellationToken cancellationToken) + { + var query = _context.PointAccounts.AsQueryable(); + + // EN: Filter by points range if provided + // VI: Lọc theo khoảng điểm nếu có + if (request.MinPoints.HasValue) + query = query.Where(p => p.AvailablePoints >= request.MinPoints.Value); + + if (request.MaxPoints.HasValue) + query = query.Where(p => p.AvailablePoints <= request.MaxPoints.Value); + + var totalCount = await query.CountAsync(cancellationToken); + + var accounts = await query + .OrderByDescending(p => p.TotalPoints) + .Skip((request.Page - 1) * request.PageSize) + .Take(request.PageSize) + .Select(p => new AdminPointAccountSummaryDto( + p.Id, + p.UserId, + p.TotalPoints, + p.AvailablePoints, + p.CreatedAt)) + .ToListAsync(cancellationToken); + + return new AdminPointAccountsListDto(accounts, totalCount, request.Page, request.PageSize); + } +} + +/// +/// EN: Handler for GetPointAccountByIdQuery (Admin). +/// VI: Handler cho GetPointAccountByIdQuery (Admin). +/// +public class GetPointAccountByIdQueryHandler : IRequestHandler +{ + private readonly WalletServiceContext _context; + + public GetPointAccountByIdQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task Handle( + GetPointAccountByIdQuery request, + CancellationToken cancellationToken) + { + var account = await _context.PointAccounts + .Include(p => p.Transactions) + .FirstOrDefaultAsync(p => p.Id == request.AccountId, cancellationToken); + + if (account == null) return null; + + return new AdminPointAccountDetailDto( + account.Id, + account.UserId, + account.TotalPoints, + account.AvailablePoints, + account.Transactions.Count, + account.CreatedAt, + account.UpdatedAt); + } +} + +/// +/// EN: Handler for SearchPointAccountsQuery (Admin). +/// VI: Handler cho SearchPointAccountsQuery (Admin). +/// +public class SearchPointAccountsQueryHandler : IRequestHandler> +{ + private readonly WalletServiceContext _context; + + public SearchPointAccountsQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task> Handle( + SearchPointAccountsQuery request, + CancellationToken cancellationToken) + { + var query = _context.PointAccounts + .Include(p => p.Transactions) + .AsQueryable(); + + if (request.UserId.HasValue) + query = query.Where(p => p.UserId == request.UserId.Value); + + var accounts = await query + .Take(50) + .Select(p => new AdminPointAccountDetailDto( + p.Id, + p.UserId, + p.TotalPoints, + p.AvailablePoints, + p.Transactions.Count, + p.CreatedAt, + p.UpdatedAt)) + .ToListAsync(cancellationToken); + + return accounts; + } +} + +/// +/// EN: Handler for GetPointsStatisticsQuery (Admin). +/// VI: Handler cho GetPointsStatisticsQuery (Admin). +/// +public class GetPointsStatisticsQueryHandler : IRequestHandler +{ + private readonly WalletServiceContext _context; + + public GetPointsStatisticsQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task Handle( + GetPointsStatisticsQuery request, + CancellationToken cancellationToken) + { + var today = DateTime.UtcNow.Date; + + var totalAccounts = await _context.PointAccounts.CountAsync(cancellationToken); + + var totalPointsIssued = await _context.PointAccounts + .SumAsync(p => p.TotalPoints, cancellationToken); + + var totalPointsAvailable = await _context.PointAccounts + .SumAsync(p => p.AvailablePoints, cancellationToken); + + // EN: Calculate spent and expired from transactions + // VI: Tính điểm đã tiêu và hết hạn từ giao dịch + var totalPointsSpent = await _context.PointTransactions + .Where(t => t.TypeId == PointTransactionType.Spend.Id) + .SumAsync(t => t.Points, cancellationToken); + + var totalPointsExpired = await _context.PointTransactions + .Where(t => t.TypeId == PointTransactionType.Expire.Id) + .SumAsync(t => t.Points, cancellationToken); + + var pointsEarnedToday = await _context.PointTransactions + .Where(t => t.CreatedAt >= today && t.TypeId == PointTransactionType.Earn.Id) + .SumAsync(t => t.Points, cancellationToken); + + var pointsSpentToday = await _context.PointTransactions + .Where(t => t.CreatedAt >= today && t.TypeId == PointTransactionType.Spend.Id) + .SumAsync(t => t.Points, cancellationToken); + + return new PointsStatisticsDto( + totalAccounts, + totalPointsIssued, + totalPointsAvailable, + totalPointsSpent, + totalPointsExpired, + pointsEarnedToday, + pointsSpentToday); + } +} diff --git a/services/wallet-service-net/src/WalletService.API/Application/Queries/AdminWalletQueryHandlers.cs b/services/wallet-service-net/src/WalletService.API/Application/Queries/AdminWalletQueryHandlers.cs new file mode 100644 index 00000000..166d6e4a --- /dev/null +++ b/services/wallet-service-net/src/WalletService.API/Application/Queries/AdminWalletQueryHandlers.cs @@ -0,0 +1,211 @@ +namespace WalletService.API.Application.Queries; + +using MediatR; +using Microsoft.EntityFrameworkCore; +using WalletService.Domain.AggregatesModel.WalletAggregate; +using WalletService.Infrastructure; + +/// +/// EN: Handler for GetAllWalletsQuery (Admin). +/// VI: Handler cho GetAllWalletsQuery (Admin). +/// +public class GetAllWalletsQueryHandler : IRequestHandler +{ + private readonly WalletServiceContext _context; + + public GetAllWalletsQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task Handle( + GetAllWalletsQuery request, + CancellationToken cancellationToken) + { + var query = _context.Wallets + .Include(w => w.Balances) + .AsQueryable(); + + // EN: Filter by status if provided + // VI: Lọc theo trạng thái nếu có + if (!string.IsNullOrEmpty(request.Status)) + { + var status = WalletStatus.FromDisplayName(request.Status); + if (status != null) + query = query.Where(w => w.StatusId == status.Id); + } + + var totalCount = await query.CountAsync(cancellationToken); + + var wallets = await query + .OrderByDescending(w => w.CreatedAt) + .Skip((request.Page - 1) * request.PageSize) + .Take(request.PageSize) + .Select(w => new AdminWalletSummaryDto( + w.Id, + w.UserId, + WalletStatus.FromValue(w.StatusId).Name, + w.Balances.Select(b => new BalanceItemDto( + CurrencyType.FromValue(b.CurrencyTypeId).Name, + b.Balance)).ToList(), + w.CreatedAt, + w.UpdatedAt)) + .ToListAsync(cancellationToken); + + return new AdminWalletsListDto(wallets, totalCount, request.Page, request.PageSize); + } +} + +/// +/// EN: Handler for GetWalletByIdQuery (Admin). +/// VI: Handler cho GetWalletByIdQuery (Admin). +/// +public class GetWalletByIdQueryHandler : IRequestHandler +{ + private readonly WalletServiceContext _context; + + public GetWalletByIdQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task Handle( + GetWalletByIdQuery request, + CancellationToken cancellationToken) + { + var wallet = await _context.Wallets + .Include(w => w.Balances) + .Include(w => w.Transactions) + .FirstOrDefaultAsync(w => w.Id == request.WalletId, cancellationToken); + + if (wallet == null) return null; + + return new AdminWalletDetailDto( + wallet.Id, + wallet.UserId, + WalletStatus.FromValue(wallet.StatusId).Name, + wallet.Balances.Select(b => new BalanceItemDto( + CurrencyType.FromValue(b.CurrencyTypeId).Name, + b.Balance)).ToList(), + wallet.Transactions.Count, + wallet.CreatedAt, + wallet.UpdatedAt); + } +} + +/// +/// EN: Handler for SearchWalletsQuery (Admin). +/// VI: Handler cho SearchWalletsQuery (Admin). +/// +public class SearchWalletsQueryHandler : IRequestHandler> +{ + private readonly WalletServiceContext _context; + + public SearchWalletsQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task> Handle( + SearchWalletsQuery request, + CancellationToken cancellationToken) + { + var query = _context.Wallets + .Include(w => w.Balances) + .Include(w => w.Transactions) + .AsQueryable(); + + if (request.UserId.HasValue) + query = query.Where(w => w.UserId == request.UserId.Value); + + if (request.WalletId.HasValue) + query = query.Where(w => w.Id == request.WalletId.Value); + + if (!string.IsNullOrEmpty(request.Status)) + { + var status = WalletStatus.FromDisplayName(request.Status); + if (status != null) + query = query.Where(w => w.StatusId == status.Id); + } + + var wallets = await query + .Take(50) // Limit results + .Select(w => new AdminWalletDetailDto( + w.Id, + w.UserId, + WalletStatus.FromValue(w.StatusId).Name, + w.Balances.Select(b => new BalanceItemDto( + CurrencyType.FromValue(b.CurrencyTypeId).Name, + b.Balance)).ToList(), + w.Transactions.Count, + w.CreatedAt, + w.UpdatedAt)) + .ToListAsync(cancellationToken); + + return wallets; + } +} + +/// +/// EN: Handler for GetWalletStatisticsQuery (Admin). +/// VI: Handler cho GetWalletStatisticsQuery (Admin). +/// +public class GetWalletStatisticsQueryHandler : IRequestHandler +{ + private readonly WalletServiceContext _context; + + public GetWalletStatisticsQueryHandler(WalletServiceContext context) + { + _context = context; + } + + public async Task Handle( + GetWalletStatisticsQuery request, + CancellationToken cancellationToken) + { + var today = DateTime.UtcNow.Date; + + var totalWallets = await _context.Wallets.CountAsync(cancellationToken); + var activeWallets = await _context.Wallets + .CountAsync(w => w.StatusId == WalletStatus.Active.Id, cancellationToken); + var frozenWallets = await _context.Wallets + .CountAsync(w => w.StatusId == WalletStatus.Frozen.Id, cancellationToken); + var closedWallets = await _context.Wallets + .CountAsync(w => w.StatusId == WalletStatus.Closed.Id, cancellationToken); + + // EN: Total balance by currency + // VI: Tổng số dư theo loại tiền tệ + var balancesByCurrency = await _context.WalletItems + .GroupBy(wi => wi.CurrencyTypeId) + .Select(g => new { CurrencyId = g.Key, Total = g.Sum(wi => wi.Balance) }) + .ToListAsync(cancellationToken); + + var totalBalanceByCurrency = balancesByCurrency.ToDictionary( + b => CurrencyType.FromValue(b.CurrencyId).Name, + b => b.Total); + + // EN: Today's transactions + // VI: Giao dịch hôm nay + var todayTransactions = await _context.WalletTransactions + .Where(t => t.CreatedAt >= today) + .SumAsync(t => t.Amount.Amount, cancellationToken); + + var todayDeposits = await _context.WalletTransactions + .Where(t => t.CreatedAt >= today && t.TypeId == TransactionType.Credit.Id) + .SumAsync(t => t.Amount.Amount, cancellationToken); + + var todayWithdrawals = await _context.WalletTransactions + .Where(t => t.CreatedAt >= today && t.TypeId == TransactionType.Debit.Id) + .SumAsync(t => t.Amount.Amount, cancellationToken); + + return new WalletStatisticsDto( + totalWallets, + activeWallets, + frozenWallets, + closedWallets, + totalBalanceByCurrency, + todayTransactions, + todayDeposits, + todayWithdrawals); + } +} diff --git a/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/PointAccountAggregate/IPointAccountRepository.cs b/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/PointAccountAggregate/IPointAccountRepository.cs index 657e1faa..be6590e5 100644 --- a/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/PointAccountAggregate/IPointAccountRepository.cs +++ b/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/PointAccountAggregate/IPointAccountRepository.cs @@ -8,6 +8,12 @@ using WalletService.Domain.SeedWork; /// public interface IPointAccountRepository : IRepository { + /// + /// EN: Get point account by ID + /// VI: Lấy tài khoản điểm theo ID + /// + Task GetByIdAsync(Guid accountId); + /// /// EN: Get point account by user ID /// VI: Lấy tài khoản điểm theo ID người dùng diff --git a/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/WalletAggregate/IWalletRepository.cs b/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/WalletAggregate/IWalletRepository.cs index e87cc6e4..f3c7b777 100644 --- a/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/WalletAggregate/IWalletRepository.cs +++ b/services/wallet-service-net/src/WalletService.Domain/AggregatesModel/WalletAggregate/IWalletRepository.cs @@ -8,6 +8,12 @@ using WalletService.Domain.SeedWork; /// public interface IWalletRepository : IRepository { + /// + /// EN: Get wallet by ID + /// VI: Lấy ví theo ID + /// + Task GetByIdAsync(Guid walletId); + /// /// EN: Get wallet by user ID /// VI: Lấy ví theo ID người dùng diff --git a/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/PointAccountRepository.cs b/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/PointAccountRepository.cs index 29d0ce7b..4654aa82 100644 --- a/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/PointAccountRepository.cs +++ b/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/PointAccountRepository.cs @@ -19,6 +19,12 @@ public class PointAccountRepository : IPointAccountRepository _context = context ?? throw new ArgumentNullException(nameof(context)); } + public async Task GetByIdAsync(Guid accountId) + { + return await _context.PointAccounts + .FirstOrDefaultAsync(p => p.Id == accountId); + } + public async Task GetByUserIdAsync(Guid userId) { return await _context.PointAccounts diff --git a/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/WalletRepository.cs b/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/WalletRepository.cs index c6f34fba..9ff8293b 100644 --- a/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/WalletRepository.cs +++ b/services/wallet-service-net/src/WalletService.Infrastructure/Repositories/WalletRepository.cs @@ -19,9 +19,17 @@ public class WalletRepository : IWalletRepository _context = context ?? throw new ArgumentNullException(nameof(context)); } + public async Task GetByIdAsync(Guid walletId) + { + return await _context.Wallets + .Include(w => w.Balances) + .FirstOrDefaultAsync(w => w.Id == walletId); + } + public async Task GetByUserIdAsync(Guid userId) { return await _context.Wallets + .Include(w => w.Balances) .FirstOrDefaultAsync(w => w.UserId == userId); }