diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index c40cb61..cbc5802 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -2139,7 +2139,8 @@ private async Task>> LoadMe from t in context.Transactions join m in context.Merchants on t.MerchantId equals m.MerchantId join cp in context.ContractProducts on new { t.ContractProductId, t.ContractId } equals new { cp.ContractProductId, cp.ContractId } - join op in context.Operators on t.OperatorId equals op.OperatorId + join op in context.Operators on t.OperatorId equals op.OperatorId into opJoin + from op in opJoin.DefaultIfEmpty() where t.TransactionType == "Sale" && t.TransactionDate >= startDate && t.TransactionDate <= endDate @@ -2147,7 +2148,7 @@ join op in context.Operators on t.OperatorId equals op.OperatorId group t by new { cp.ContractProductReportingId, - op.Name, + OperatorName = op == null ? string.Empty : op.Name, cp.ProductName, t.IsAuthorised } @@ -2156,7 +2157,7 @@ into g { ContractProductReportingId = g.Key.ContractProductReportingId, ProductName = g.Key.ProductName, - OperatorName = g.Key.Name, + OperatorName = g.Key.OperatorName, IsAuthorised = g.Key.IsAuthorised, SalesCount = g.Count(), SalesValue = g.Sum(x => x.TransactionAmount) @@ -2174,7 +2175,8 @@ private async Task>> L (from t in context.Transactions join m in context.Merchants on t.MerchantId equals m.MerchantId join cp in context.ContractProducts on new { t.ContractProductId, t.ContractId } equals new { cp.ContractProductId, cp.ContractId } - join op in context.Operators on t.OperatorId equals op.OperatorId + join op in context.Operators on t.OperatorId equals op.OperatorId into opJoin + from op in opJoin.DefaultIfEmpty() where t.TransactionType == "Sale" && t.TransactionDate >= startDate && t.TransactionDate <= endDate @@ -2184,7 +2186,7 @@ orderby t.TransactionDateTime descending { Reference = t.TransactionNumber, Product = cp.ProductName, - Operator = op.Name, + Operator = op == null ? string.Empty : op.Name, Status = t.IsAuthorised ? "Successful" : "Failed", Amount = t.TransactionAmount, TransactionDateTime = t.TransactionDateTime diff --git a/EstateReportingAPI.IntegrationTests/TransactionsEndpointTests.cs b/EstateReportingAPI.IntegrationTests/TransactionsEndpointTests.cs index 6b69b79..cd170ec 100644 --- a/EstateReportingAPI.IntegrationTests/TransactionsEndpointTests.cs +++ b/EstateReportingAPI.IntegrationTests/TransactionsEndpointTests.cs @@ -1401,6 +1401,61 @@ public async Task TransactionsEndpoint_MerchantDailyPerformanceSummary_ReturnsMe } } + [Fact] + public async Task TransactionsEndpoint_MerchantDailyPerformanceSummary_PreservesTransactionsWithoutOperatorRows() + { + TransactionProcessor.Database.Entities.Merchant merchant = this.merchantsList.Single(m => m.Name == "Test Merchant 1"); + var contract = this.contractList.Single(c => c.contractName == "Safaricom Contract"); + var product = this.contractProducts.Single(cp => cp.Key == contract.contractId).Value.Single(p => p.productName == "50 KES Topup"); + DateTime transactionDate = DateTime.Now.Date; + + List transactions = [ + await this.helper.BuildTransactionX( + transactionDate.AddHours(9), + merchant.MerchantId, + contract.operatorId, + contract.contractId, + product.productId, + "0000", + product.productValue, + 2001), + await this.helper.BuildTransactionX( + transactionDate.AddHours(10), + merchant.MerchantId, + Guid.NewGuid(), + contract.contractId, + product.productId, + "0000", + product.productValue, + 2002) + ]; + + await this.helper.AddTransactionsX(transactions); + + MerchantDailyPerformanceSummaryRequest request = new() + { + MerchantReportingId = merchant.MerchantReportingId, + StartDate = transactionDate, + EndDate = transactionDate + }; + + var result = await this.CreateAndSendHttpRequestMessage( + $"{this.BaseRoute}/merchantdailyperformancesummary", + StringSerialiser.Serialise(request), + CancellationToken.None); + + result.IsSuccess.ShouldBeTrue(); + + MerchantDailyPerformanceSummaryResponse response = result.Data; + response.ShouldNotBeNull(); + response.Metrics.ShouldNotBeNull(); + response.DrillDownTransactions.ShouldNotBeNull(); + + response.Metrics.Single(m => m.Title == "Total Sales Count").Value.ShouldBe(2); + response.Metrics.Single(m => m.Title == "Total Sales Value").Value.ShouldBe(transactions.Sum(t => t.TransactionAmount)); + response.DrillDownTransactions.Count.ShouldBe(2); + } + [Fact] public async Task TransactionsEndpoint_MerchantDailyPerformanceSummary_NoSales_ReturnsStableMetricCategories() {