Reporting

Reporting is the end product of operations and is especially important for users and managers of organizations and companies to use reports to meet their needs and users, faster and more dynamically.

Operational Report

This type of report is a quick and simple report that can be used for quick reporting and applying various filters to any entity. Creating this type of report is very simple and has a simple structure, and it is easy to apply various and professional filters. This type of report has one input model view and one output model view. Its Input model view includes filters that must be applied, but the report can have no filters and inputs. You can easily report from different tables and have a variety of reports. These types of operational reports are known as ListService in the structure of the AUA framework. In each report, if a non-zero value is sent to TotalCount from the input. The framework will not perform the TotalCount computations and will return the value with no change.


First: Create SearchVm

public class AppUserSearchVm : BaseSearchVm
{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string UserName { get; set; }

    public bool? IsActive { get; set; }

}


Second : Create ListDto (to return the output)

public class AppUserListDto : IHaveCustomMappings
{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string UserName { get; set; }

    public string FullName => $"{FirstName} {LastName}";

    public string Password { get; set; }

    public string Phone { get; set; }

    public string Email { get; set; }

    public DateTime RegistrationDate { get; set; }

    public string RegistrationDatePersian => RegistrationDate.ToPersianDate();

    public ICollection<RoleDto>UserRoleDtos { get; set; }
   
    public void ConfigureMapping(Profile configuration)
    {

        configuration.CreateMap<AppUser, AppUserListDto>()
                     .ForMember(p => p.UserRoleDtos, p => p.MapFrom(q => q.UserRoles.Select(r => r.Role)));

    }

}


Third : Create interface (To Injection)
                
public interface IAppUserListService : IBaseListService<AppUser, AppUserListDto>
{
    Task<ListResultVm<AppUserListDto>> ListAsync(AppUserSearchVm appUserSearchVm);
}


Fourth : Create ListService (To apply filters)
                
public sealed class AppUserListService : 
                         BaseListService<AppUser, AppUserListDto, AppUserSearchVm>
                         , IAppUserListService
{
    
    public AppUserListService(IUnitOfWork unitOfWork, IMapper mapperInstance) : base(unitOfWork, mapperInstance)
    {
    
    }

    
    public async Task<ListResultVm<AppUserListDto>> ListAsync(AppUserSearchVm appUserSearchVm)
    {
        SetSearchVm(appUserSearchVm);
    
        ApplyUserNameFilter();
        ApplyLastNameFilter();
        ApplyFirstNameFilter();
        ApplyIsActiveFilters();
    
    
        return await CreateListVmResultAsync();
    }

    
    private void ApplyUserNameFilter()
    {
        if (string.IsNullOrWhiteSpace(SearchVm.UserName))
            return;
    
        Query = Query.Where(p => p.UserName.Contains(SearchVm.UserName));
    }

    
    private void ApplyLastNameFilter()
    {
        if (string.IsNullOrWhiteSpace(SearchVm.LastName))
            return;
    
        Query = Query.Where(p => p.LastName.Contains(SearchVm.LastName));
    }

    
    private void ApplyFirstNameFilter()
    {
        if (string.IsNullOrWhiteSpace(SearchVm.FirstName))
            return;
    
        Query = Query.Where(p => p.FirstName.Contains(SearchVm.FirstName));
    }

    
    private void ApplyIsActiveFilters()
    {
        if (!SearchVm.IsActive.HasValue)
            return;
    
        Query = Query.Where(p => p.IsActive == SearchVm.IsActive);
    }

}

 

Enterprise Report

This type of reporting is very complete and professional and has a structure similar to ListServices. In your Enterprise Report, using the Specification Patterns of operators, you can easily perform the most difficult report. It has a professional and interesting structure. In each report, TotalCount is automatically calculated. In each report, if a non-zero value is sent to TotalCount from the input. The framework will not perform the TotalCount computations and will return the value with no change.


            
public class UserAccessReportSearchVm : BaseSearchVm
{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string UserName { get; set; }

    public bool? IsActive { get; set; }

    public List<SelectListItem> RecordStatusItems { get; set; }

    public string RoleTitle { get; set; }

    public string UserAccessTitle { get; set; }

}


View Model of Report output:


            
public class UserAccessReportGridVm : BaseEntityDto<long>, IHaveCustomMappings
{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string UserName { get; set; }

    public string RoleTitle { get; set; }

    public string FullName => $"{FirstName} {LastName}";

    public string Password { get; set; }

    public string Phone { get; set; }

    public string Email { get; set; }

    public bool IsActive { get; set; }

    public ICollection<Role> UserRoles { get; set; }

    public IEnumerable<UserAccess> UserAccess { get; set; }

    public string UserRolesTitles => string.Join("", UserRoles.Select(p => p.Title));

    public string UserAccessTitles => string.Join("", UserAccess.Select(p => p.Title));
    
    public void ConfigureMapping(Profile configuration)
    {
        configuration.CreateMap<AppUser, UserAccessReportGridVm>()
                     .ForMember(p => p.UserRoles, p => p.MapFrom(q => q.UserRoles.Select(r => r.Role)))
                     .ForMember(p => p.UserAccess, p => p.MapFrom(q => q.UserRoles.SelectMany(t => 
                                                        t.Role.UserRoleAccess.Select(m => m.UserAccess))));
    }

}


After creating the search view and grid view of the model, we write a search filter to apply the filters


            
public class UserAccessReportFilter : Specification<AppUser>
{

    private readonly UserAccessReportSearchVm _searchVm;

    private Expression<Func<AppUser, bool>> _expression == p => true;

    protected bool IsEmptyFilter => _searchVm == null;
    
    public UserAccessReportFilter(UserAccessReportSearchVm searchVm)
    {
        _searchVm = searchVm;
    }
    
    public override Expression<Func<AppUser, bool>> IsSatisfiedBy()
    {

        if(IsEmptyFilter) return p => true;
        
        ApplyDefaultFilter();
        ApplyFirstNameFilter();
        ApplyLastNameFilter();
        ApplyUserNameFilter();
        ApplyIsActiveFilter();
        ApplyRoleTitleFilter();
        ApplyUserAccessTitleFilter();
        
        return _expression;

    }
    
    private void ApplyDefaultFilter()
    {
        //TODO: if needed
    }
    
    private void ApplyFirstNameFilter()
    {

        if(string.IsNullOrWhiteSpace(_searchVm.FirstName))
        return;
        
        _expression = _expression.And(p => p.FirstName.Contains(_searchVm.FirstName));

    }
    
    private void ApplyLastNameFilter()
    {

        if(string.IsNullOrWhiteSpace(_searchVm.LastName))
        return;
        
        _expression = _expression.And(p => p.LastName.Contains(_searchVm.LastName));

    }
    
    private void ApplyUserNameFilter()
    {

        if(string.IsNullOrWhiteSpace(_searchVm.UserName))
        return;
        
        _expression = _expression.And(p => p.UserName.Contains(_searchVm.UserName));

    }
    
    private void ApplyIsActiveFilter()
    {

        if(_searchVm.IsActive == null)
        return;
        
        _expression = _expression.And(p => p.IsActive == _searchVm.IsActive);

    }
    
    private void ApplyRoleTitleFilter()
    {

        if(string.IsNullOrWhiteSpace(_searchVm.RoleTitle))
        return;
        
        _expression = _expression.And(p => p.UserRoles.Any(r  => r.Role.Title.Contains(_searchVm.RoleTitle)));

    }
    
    private void ApplyUserAccessTitleFilter()
    {

        if(string.IsNullOrWhiteSpace(_searchVm.UserAccessTitle))
        return;
        
        _expression = _expression.And(p => p.UserRoles.Any(r => r.Role.UserRoleAccess
                                   .Any(a => a.UserAccess.Title.Contains(_searchVm.UserAccessTitle))));

    }
}


Reporting

Reporting in youtube More videos

Reporting in youtube More videos



Filter Reporting