Implement repository pattern for AuditLog entity for Sprint 2 Story 1 Task 2. Changes: - Created IAuditLogRepository interface with 6 query methods - Implemented AuditLogRepository with efficient querying - Registered repository in DI container - All queries use AsNoTracking for read-only operations Query Methods: - GetByIdAsync: Get single audit log by ID - GetByEntityAsync: Get audit history for specific entity - GetByUserAsync: Get user activity with pagination - GetRecentAsync: Get recent audit logs - AddAsync: Add new audit log - GetCountAsync: Get total audit log count Performance: - All queries automatically filtered by TenantId (Global Query Filter) - Efficient use of composite indexes - AsNoTracking for read-only operations Testing: - All tests passing (192 domain + 113 identity + 8 arch + 32 app + 12 infra = 357 tests) - No compilation errors - Zero test failures 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
73 lines
2.4 KiB
C#
73 lines
2.4 KiB
C#
using ColaFlow.Modules.ProjectManagement.Domain.Entities;
|
|
using ColaFlow.Modules.ProjectManagement.Domain.Repositories;
|
|
using ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Repositories;
|
|
|
|
public class AuditLogRepository : IAuditLogRepository
|
|
{
|
|
private readonly PMDbContext _context;
|
|
|
|
public AuditLogRepository(PMDbContext context)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
public async Task<AuditLog?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
|
|
{
|
|
return await _context.AuditLogs
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(a => a.Id == id, cancellationToken);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<AuditLog>> GetByEntityAsync(
|
|
string entityType,
|
|
Guid entityId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return await _context.AuditLogs
|
|
.AsNoTracking()
|
|
.Where(a => a.EntityType == entityType && a.EntityId == entityId)
|
|
.OrderByDescending(a => a.Timestamp)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<AuditLog>> GetByUserAsync(
|
|
Guid userId,
|
|
int pageNumber = 1,
|
|
int pageSize = 50,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return await _context.AuditLogs
|
|
.AsNoTracking()
|
|
.Where(a => a.UserId == userId)
|
|
.OrderByDescending(a => a.Timestamp)
|
|
.Skip((pageNumber - 1) * pageSize)
|
|
.Take(pageSize)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<AuditLog>> GetRecentAsync(
|
|
int count = 100,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return await _context.AuditLogs
|
|
.AsNoTracking()
|
|
.OrderByDescending(a => a.Timestamp)
|
|
.Take(count)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task AddAsync(AuditLog auditLog, CancellationToken cancellationToken = default)
|
|
{
|
|
await _context.AuditLogs.AddAsync(auditLog, cancellationToken);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<int> GetCountAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
return await _context.AuditLogs.CountAsync(cancellationToken);
|
|
}
|
|
}
|