Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public record TransactionSummaryByMerchantQuery(Guid EstateId, TransactionSummar
public record TransactionSummaryByOperatorQuery(Guid EstateId, TransactionSummaryByOperatorRequest Request) : IRequest<Result<TransactionSummaryByOperatorResponse>>;
public record ProductPerformanceQuery(Guid EstateId, DateTime StartDate, DateTime EndDate) : IRequest<Result<ProductPerformanceResponse>>;
public record TransactionMixSummaryQuery(Guid EstateId, TransactionMixSummaryRequest Request) : IRequest<Result<TransactionMixSummaryResponse>>;
public record GetRecentActivityReceiptReportQuery(Guid EstateId, GetRecentActivityReceiptReportRequest Request) : IRequest<Result<GetRecentActivityReceiptReportResponse>>;
public record TodaysSalesByHour(Guid estateId, DateTime comparisonDate) : IRequest<Result<List<Models.TodaysSalesByHour>>>;
public record MerchantDailyPerformanceSummaryQuery(Guid EstateId, MerchantDailyPerformanceSummaryRequest Request) : IRequest<Result<MerchantDailyPerformanceSummaryResponse>>;
}
}
151 changes: 147 additions & 4 deletions EstateReportingAPI.BusinessLogic/ReportingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ Task<Result<TransactionDetailReportResponse>> GetTransactionDetailReport(Transac
Task<Result<TransactionSummaryByMerchantResponse>> GetTransactionSummaryByMerchantReport(TransactionQueries.TransactionSummaryByMerchantQuery request,
CancellationToken cancellationToken);
Task<Result<TransactionSummaryByOperatorResponse>> GetTransactionSummaryByOperatorReport(TransactionQueries.TransactionSummaryByOperatorQuery request,
CancellationToken cancellationToken);
CancellationToken cancellationToken);
Task<Result<ProductPerformanceResponse>> GetProductPerformanceReport(TransactionQueries.ProductPerformanceQuery request,
CancellationToken cancellationToken);
Task<Result<TransactionMixSummaryResponse>> GetTransactionMixSummary(TransactionQueries.TransactionMixSummaryQuery request,
CancellationToken cancellationToken);
CancellationToken cancellationToken);
Task<Result<GetRecentActivityReceiptReportResponse>> GetRecentActivityReceiptReport(TransactionQueries.GetRecentActivityReceiptReportQuery request,
CancellationToken cancellationToken);

Task<Result<List<TodaysSalesByHour>>> GetTodaysSalesByHour(TransactionQueries.TodaysSalesByHour request,
CancellationToken cancellationToken);
Expand Down Expand Up @@ -108,6 +110,19 @@ private static async Task<Result<List<T>>> ExecuteQuerySafeToList<T>(IQueryable<
}
}

private static async Task<Result<int>> ExecuteQuerySafeCount(IQueryable query,
CancellationToken cancellationToken,
string contextMessage = null) {
try {
int count = await query.CountAsync(cancellationToken);
return Result.Success(count);
}
catch (Exception ex) {
string msg = contextMessage == null ? $"Error executing query: {ex.Message}" : $"{contextMessage}: {ex.Message}";
return Result.Failure(msg);
}
}

private static async Task<Result<T>> ExecuteQuerySafeSingleOrDefault<T>(IQueryable<T> query,
CancellationToken cancellationToken,
string contextMessage = null) {
Expand Down Expand Up @@ -1293,9 +1308,117 @@ public async Task<Result<TransactionMixSummaryResponse>> GetTransactionMixSummar
return Result.Success(BuildTransactionMixSummaryResponse(queryResults, request.Request));
}

public async Task<Result<GetRecentActivityReceiptReportResponse>> GetRecentActivityReceiptReport(TransactionQueries.GetRecentActivityReceiptReportQuery request,
CancellationToken cancellationToken) {
using ResolvedDbContext<EstateManagementContext>? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString());
await using EstateManagementContext context = resolvedContext.Context;

RecentActivityReceiptRequestParameters parameters = BuildRecentActivityReceiptRequestParameters(request.Request);
IQueryable<RecentActivityReceiptQueryResult> query = BuildRecentActivityReceiptQuery(context, parameters);

var totalCountResult = await ExecuteQuerySafeCount(query, cancellationToken, "Error counting recent activity receipt report rows");
if (totalCountResult.IsFailed)
return ResultHelpers.CreateFailure(totalCountResult);

int totalCount = totalCountResult.Data;
if (totalCount == 0)
return Result.Success(BuildEmptyRecentActivityReceiptReportResponse(parameters));

var pageQuery = query.Skip((parameters.PageNumber - 1) * parameters.PageSize).Take(parameters.PageSize);
var pageResult = await ExecuteQuerySafeToList(pageQuery, cancellationToken, "Error retrieving recent activity receipt report");
if (pageResult.IsFailed)
return ResultHelpers.CreateFailure(pageResult);

return Result.Success(BuildRecentActivityReceiptReportResponse(parameters, totalCount, pageResult.Data));
}

private static RecentActivityReceiptRequestParameters BuildRecentActivityReceiptRequestParameters(GetRecentActivityReceiptReportRequest request) {
return new RecentActivityReceiptRequestParameters {
ReportDate = request.ReportDate.Date,
MerchantReportingId = request.MerchantReportingId,
SearchText = request.SearchText?.Trim(),
PageNumber = request.PageNumber > 0 ? request.PageNumber : 1,
PageSize = request.PageSize > 0 ? request.PageSize : 10
};
}

private static IQueryable<RecentActivityReceiptQueryResult> BuildRecentActivityReceiptQuery(EstateManagementContext context,
RecentActivityReceiptRequestParameters parameters) {
IQueryable<RecentActivityReceiptQueryResult> query = from t in context.Transactions
join m in context.Merchants on t.MerchantId equals m.MerchantId
join o in context.Operators on t.OperatorId equals o.OperatorId
join cp in context.ContractProducts on new { t.ContractProductId, t.ContractId } equals new { cp.ContractProductId, cp.ContractId }
where t.TransactionDate == parameters.ReportDate
select new RecentActivityReceiptQueryResult {
TransactionDateTime = t.TransactionDateTime,
MerchantReportingId = m.MerchantReportingId,
Reference = t.TransactionNumber,
TransactionType = t.TransactionType,
Product = cp.ProductName,
Operator = o.Name,
Status = t.IsAuthorised ? "Successful" : "Failed",
Amount = t.TransactionAmount,
ReceiptReference = t.TransactionReference
};

return ApplyRecentActivityReceiptFilters(query, parameters).OrderByDescending(q => q.TransactionDateTime);
}

private static IQueryable<RecentActivityReceiptQueryResult> ApplyRecentActivityReceiptFilters(IQueryable<RecentActivityReceiptQueryResult> query,
RecentActivityReceiptRequestParameters parameters) {
if (parameters.MerchantReportingId.HasValue)
query = query.Where(q => q.MerchantReportingId == parameters.MerchantReportingId.Value);

if (string.IsNullOrWhiteSpace(parameters.SearchText) == false)
query = query.Where(q =>
q.Reference.Contains(parameters.SearchText) ||
q.TransactionType.Contains(parameters.SearchText) ||
q.Product.Contains(parameters.SearchText) ||
q.Operator.Contains(parameters.SearchText) ||
q.Status.Contains(parameters.SearchText) ||
q.ReceiptReference.Contains(parameters.SearchText));

return query;
}

private static GetRecentActivityReceiptReportResponse BuildEmptyRecentActivityReceiptReportResponse(RecentActivityReceiptRequestParameters parameters) {
return new GetRecentActivityReceiptReportResponse {
ReportDate = parameters.ReportDate,
PageNumber = parameters.PageNumber,
PageSize = parameters.PageSize,
TotalCount = 0,
Items = []
};
}

private static GetRecentActivityReceiptReportResponse BuildRecentActivityReceiptReportResponse(RecentActivityReceiptRequestParameters parameters,
int totalCount,
List<RecentActivityReceiptQueryResult> queryResults) {
return new GetRecentActivityReceiptReportResponse {
ReportDate = parameters.ReportDate,
PageNumber = parameters.PageNumber,
PageSize = parameters.PageSize,
TotalCount = totalCount,
Items = queryResults.Select(MapRecentActivityReceiptItem).ToList()
};
}

private static RecentActivityReceiptItemDto MapRecentActivityReceiptItem(RecentActivityReceiptQueryResult item) {
return new RecentActivityReceiptItemDto {
Reference = item.Reference,
TransactionType = item.TransactionType,
Product = item.Product,
Operator = item.Operator,
Status = item.Status,
Amount = item.Amount,
TransactionDateTime = item.TransactionDateTime,
ReceiptReference = item.ReceiptReference
};
}

private static IQueryable<ProductPerformanceItemData> BuildProductPerformanceQuery(EstateManagementContext context,
DateTime startDate,
DateTime endDate,
DateTime startDate,
DateTime endDate,
decimal grandTotalAmount) {
return from t in context.Transactions
join cp in context.ContractProducts on new { t.ContractProductId, t.ContractId } equals new { cp.ContractProductId, cp.ContractId }
Expand Down Expand Up @@ -2026,6 +2149,26 @@ private static List<DrillDownTransaction> MapMerchantDailyPerformanceRecentSales
}).ToList();
}

private sealed class RecentActivityReceiptQueryResult {
public DateTime TransactionDateTime { get; init; }
public int MerchantReportingId { get; init; }
public string Reference { get; init; }
public string? TransactionType { get; init; }
public string? Product { get; init; }
public string? Operator { get; init; }
public string? Status { get; init; }
public decimal Amount { get; init; }
public string? ReceiptReference { get; init; }
}

private sealed class RecentActivityReceiptRequestParameters {
public DateTime ReportDate { get; init; }
public int? MerchantReportingId { get; init; }
public string? SearchText { get; init; }
public int PageNumber { get; init; }
public int PageSize { get; init; }
}

private sealed class TransactionDetailQueryResult {
public Guid TransactionId { get; init; }
public DateTime TransactionDateTime { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class TransactionRequestHandler : IRequestHandler<TransactionQueries.Toda
IRequestHandler<TransactionQueries.TransactionSummaryByOperatorQuery, Result<TransactionSummaryByOperatorResponse>>,
IRequestHandler<TransactionQueries.ProductPerformanceQuery, Result<ProductPerformanceResponse>>,
IRequestHandler<TransactionQueries.TransactionMixSummaryQuery, Result<TransactionMixSummaryResponse>>,
IRequestHandler<TransactionQueries.GetRecentActivityReceiptReportQuery, Result<GetRecentActivityReceiptReportResponse>>,
IRequestHandler<TransactionQueries.TodaysSalesByHour, Result<List<TodaysSalesByHour>>>,
IRequestHandler<TransactionQueries.MerchantDailyPerformanceSummaryQuery, Result<MerchantDailyPerformanceSummaryResponse>>

Expand Down Expand Up @@ -60,6 +61,12 @@ public async Task<Result<TransactionMixSummaryResponse>> Handle(TransactionQueri
return await this.Manager.GetTransactionMixSummary(request, cancellationToken);
}

public async Task<Result<GetRecentActivityReceiptReportResponse>> Handle(TransactionQueries.GetRecentActivityReceiptReportQuery request,
CancellationToken cancellationToken)
{
return await this.Manager.GetRecentActivityReceiptReport(request, cancellationToken);
}

public async Task<Result<List<TodaysSalesByHour>>> Handle(TransactionQueries.TodaysSalesByHour request,
CancellationToken cancellationToken) {
return await this.Manager.GetTodaysSalesByHour(request, cancellationToken);
Expand All @@ -69,4 +76,4 @@ public async Task<Result<MerchantDailyPerformanceSummaryResponse>> Handle(Transa
CancellationToken cancellationToken) {
return await this.Manager.GetMerchantDailyPerformanceSummary(request, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace EstateReportingAPI.DataTransferObjects;

public class GetRecentActivityReceiptReportRequest
{
public DateTime ReportDate { get; set; }
public int? MerchantReportingId { get; set; }
public string? SearchText { get; set; }
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;

namespace EstateReportingAPI.DataTransferObjects;

public class GetRecentActivityReceiptReportResponse
{
public DateTime ReportDate { get; set; }
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public List<RecentActivityReceiptItemDto> Items { get; set; } = [];
}

public class RecentActivityReceiptItemDto
{
public string? Reference { get; set; }
public string? TransactionType { get; set; }
public string? Product { get; set; }
public string? Operator { get; set; }
public string? Status { get; set; }
public decimal Amount { get; set; }
public DateTime TransactionDateTime { get; set; }
public string? ReceiptReference { get; set; }
}
Loading
Loading