Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add audit trail features #42

Merged
merged 3 commits into from
Sep 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>ExportApprovalDatasQueryHandler.resx</DependentUpon>
</Compile>
<Compile Update="Resources\Features\AuditTrails\Queries\Export\ExportAuditTrailsQuery.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ExportAuditTrailsQuery.resx</DependentUpon>
</Compile>
<Compile Update="Resources\KeyValues\Commands\Import\ImportKeyValuesCommandHandler.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
Expand Down Expand Up @@ -111,6 +116,10 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ExportApprovalDatasQueryHandler.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Features\AuditTrails\Queries\Export\ExportAuditTrailsQuery.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ExportAuditTrailsQuery.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Resources\KeyValues\Commands\Import\ImportKeyValuesCommandHandler.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ImportKeyValuesCommandHandler.Designer.cs</LastGenOutput>
Expand Down
2 changes: 2 additions & 0 deletions src/Application/Common/Interfaces/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System.Threading;
using System.Threading.Tasks;
using CleanArchitecture.Razor.Domain.Entities;
using CleanArchitecture.Razor.Domain.Entities.Audit;
using CleanArchitecture.Razor.Domain.Entities.Worflow;
using Microsoft.EntityFrameworkCore;

namespace CleanArchitecture.Razor.Application.Common.Interfaces
{
public interface IApplicationDbContext
{
DbSet<AuditTrail> AuditTrails { get; set; }
DbSet<Customer> Customers { get; set; }
DbSet<DocumentType> DocumentTypes { get; set; }
DbSet<Document> Documents { get; set; }
Expand Down
39 changes: 39 additions & 0 deletions src/Application/Features/AuditTrails/DTOs/AuditTrailDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using AutoMapper;
using CleanArchitecture.Razor.Application.Common.Mappings;
using CleanArchitecture.Razor.Domain.Entities.Audit;

namespace CleanArchitecture.Razor.Application.Features.AuditTrails.DTOs
{
public class AuditTrailDto : IMapFrom<AuditTrail>
{
public void Mapping(Profile profile)
{
profile.CreateMap<AuditTrail, AuditTrailDto>()
.ForMember(x => x.AuditType, s => s.MapFrom(y => y.AuditType.ToString()))
.ForMember(x => x.OldValues, s => s.MapFrom(y => JsonSerializer.Serialize(y.OldValues, null)))
.ForMember(x => x.NewValues, s => s.MapFrom(y => JsonSerializer.Serialize(y.NewValues, null)))
.ForMember(x => x.PrimaryKey, s => s.MapFrom(y => JsonSerializer.Serialize(y.PrimaryKey, null)))
.ForMember(x => x.AffectedColumns, s => s.MapFrom(y => JsonSerializer.Serialize(y.AffectedColumns, null)))
;

}
public int Id { get; set; }
public string UserId { get; set; }
public string AuditType { get; set; }
public string TableName { get; set; }
public DateTime DateTime { get; set; }
public string OldValues { get; set; }
public string NewValues { get; set; }
public string AffectedColumns { get; set; }
public string PrimaryKey { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using CleanArchitecture.Razor.Application.Common.Extensions;
using CleanArchitecture.Razor.Application.Common.Interfaces;
using CleanArchitecture.Razor.Domain.Entities;
using System.Linq.Dynamic.Core;
using MediatR;
using Microsoft.EntityFrameworkCore;
using AutoMapper.QueryableExtensions;
using Microsoft.Extensions.Localization;
using CleanArchitecture.Razor.Application.Features.AuditTrails.DTOs;
using CleanArchitecture.Razor.Domain.Entities.Worflow;
using CleanArchitecture.Razor.Domain.Entities.Audit;

namespace CleanArchitecture.Razor.Application.Features.AuditTrails.Queries.Export
{
public class ExportAuditTrailsQuery : IRequest<byte[]>
{
public string filterRules { get; set; }
public string sort { get; set; } = "Id";
public string order { get; set; } = "desc";
}

public class ExportAuditTrailsQueryHandler :
IRequestHandler<ExportAuditTrailsQuery, byte[]>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
private readonly IExcelService _excelService;
private readonly IStringLocalizer<ExportAuditTrailsQueryHandler> _localizer;

public ExportAuditTrailsQueryHandler(
IApplicationDbContext context,
IMapper mapper,
IExcelService excelService,
IStringLocalizer<ExportAuditTrailsQueryHandler> localizer
)
{
_context = context;
_mapper = mapper;
_excelService = excelService;
_localizer = localizer;
}

public async Task<byte[]> Handle(ExportAuditTrailsQuery request, CancellationToken cancellationToken)
{
var filters = PredicateBuilder.FromFilter<AuditTrail>(request.filterRules);
var data = await _context.AuditTrails
.Where(filters)
.OrderBy($"{request.sort} {request.order}")
.ProjectTo<AuditTrailDto>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
var result = await _excelService.ExportAsync(data,
new Dictionary<string, Func<AuditTrailDto, object>>()
{
//{ _localizer["Id"], item => item.Id },
{ _localizer["Date Time"], item => item.DateTime.ToString("yyyy-MM-dd HH:mm:ss") },
{ _localizer["Table Name"], item => item.TableName },
{ _localizer["Audit Type"], item => item.AuditType },
{ _localizer["Old Values"], item => item.OldValues },
{ _localizer["New Values"], item => item.NewValues },
{ _localizer["Primary Key"], item => item.PrimaryKey },
}, _localizer["AuditTrails"]
);
return result;
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using CleanArchitecture.Razor.Application.Common.Extensions;
using CleanArchitecture.Razor.Application.Common.Interfaces;
using CleanArchitecture.Razor.Application.Common.Models;
using CleanArchitecture.Razor.Application.Models;
using CleanArchitecture.Razor.Domain.Entities;
using System.Linq.Dynamic.Core;
using MediatR;
using CleanArchitecture.Razor.Application.Common.Mappings;
using AutoMapper.QueryableExtensions;
using CleanArchitecture.Razor.Application.Common.Specification;
using CleanArchitecture.Razor.Application.Features.AuditTrails.DTOs;
using CleanArchitecture.Razor.Domain.Entities.Audit;

namespace CleanArchitecture.Razor.Application.AuditTrails.Queries.PaginationQuery
{
public class AuditTrailsWithPaginationQuery : PaginationRequest, IRequest<PaginatedData<AuditTrailDto>>
{


}
public class AuditTrailsQueryHandler : IRequestHandler<AuditTrailsWithPaginationQuery, PaginatedData<AuditTrailDto>>
{
private readonly ICurrentUserService _currentUserService;
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;

public AuditTrailsQueryHandler(
ICurrentUserService currentUserService,
IApplicationDbContext context,
IMapper mapper
)
{
_currentUserService = currentUserService;
_context = context;
_mapper = mapper;
}
public async Task<PaginatedData<AuditTrailDto>> Handle(AuditTrailsWithPaginationQuery request, CancellationToken cancellationToken)
{
var filters = PredicateBuilder.FromFilter<AuditTrail>(request.FilterRules);

var data = await _context.AuditTrails
.Where(filters)
.OrderBy($"{request.Sort} {request.Order}")
.ProjectTo<AuditTrailDto>(_mapper.ConfigurationProvider)
.PaginatedDataAsync(request.Page, request.Rows);

return data;
}


}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading