Added the APi to get count of pending expenses
This commit is contained in:
parent
548e714ea9
commit
590476a8aa
@ -801,11 +801,18 @@ namespace Marco.Pms.Services.Controllers
|
||||
return await _permission.HasPermission(PermissionsMaster.ExpenseProcess, loggedInEmployee.Id);
|
||||
});
|
||||
|
||||
await Task.WhenAll(hasReviewPermissionTask, hasApprovePermissionTask, hasProcessPermissionTask); // [Parallel Await]
|
||||
var hasManagePermissionTask = Task.Run(async () =>
|
||||
{
|
||||
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
return await _permission.HasPermission(PermissionsMaster.ExpenseManage, loggedInEmployee.Id);
|
||||
});
|
||||
|
||||
await Task.WhenAll(hasReviewPermissionTask, hasApprovePermissionTask, hasProcessPermissionTask, hasManagePermissionTask); // [Parallel Await]
|
||||
|
||||
var hasReviewPermission = hasReviewPermissionTask.Result;
|
||||
var hasApprovePermission = hasApprovePermissionTask.Result;
|
||||
var hasProcessPermission = hasProcessPermissionTask.Result;
|
||||
var hasManagePermission = hasManagePermissionTask.Result;
|
||||
|
||||
_logger.LogInfo(
|
||||
"Permissions resolved: Review={Review}, Approve={Approve}, Process={Process}",
|
||||
@ -813,61 +820,92 @@ namespace Marco.Pms.Services.Controllers
|
||||
|
||||
// Build base query: read-only, tenant-scoped
|
||||
var baseQuery = _context.Expenses
|
||||
.AsNoTracking() // Reduce tracking overhead for read-only list
|
||||
.Where(e => e.IsActive && e.TenantId == tenantId); // [Base Filter]
|
||||
|
||||
// Important: fix operator precedence by grouping OR conditions
|
||||
// Pending means Draft always, plus role-gated statuses
|
||||
var pendingQuery = baseQuery
|
||||
.Include(e => e.PaidBy)
|
||||
.Include(e => e.CreatedBy)
|
||||
.Include(e => e.ProcessedBy)
|
||||
.Include(e => e.ApprovedBy)
|
||||
.Include(e => e.ReviewedBy)
|
||||
.Include(e => e.PaymentMode)
|
||||
.Include(e => e.Project)
|
||||
.Include(e => e.PaymentMode)
|
||||
.Include(e => e.ExpensesType)
|
||||
.Include(e => e.Status)
|
||||
.AsNoTracking()
|
||||
.Where(e =>
|
||||
(e.StatusId == Draft && e.CreatedById == loggedInEmployee.Id)
|
||||
|| (hasReviewPermission && e.StatusId == Review)
|
||||
|| (hasApprovePermission && e.StatusId == Approve)
|
||||
|| (hasProcessPermission && e.StatusId == ProcessPending)); // [Correct Precedence]
|
||||
.AsNoTracking() // Reduce tracking overhead for read-only list
|
||||
.Where(e => e.IsActive && e.TenantId == tenantId && e.StatusId != Processed && e.Status != null); // [Base Filter]
|
||||
|
||||
// Project to DTO in SQL to avoid heavy Include graph.
|
||||
if (projectId.HasValue)
|
||||
pendingQuery = pendingQuery.Where(e => e.ProjectId == projectId);
|
||||
baseQuery = baseQuery.Where(e => e.ProjectId == projectId);
|
||||
|
||||
// Prefer ProjectTo when profiles exist; otherwise project minimal fields
|
||||
var response = await pendingQuery
|
||||
.Where(e => e.Status != null && e.ExpensesType != null && e.PaymentMode != null && e.Project != null && e.CreatedBy != null)
|
||||
.Select(e => new
|
||||
{
|
||||
Id = e.Id,
|
||||
Amount = e.Amount,
|
||||
TransactionDate = e.TransactionDate,
|
||||
StatusId = e.StatusId,
|
||||
StatusName = e.Status!.Name,
|
||||
ExpenseTypeName = e.ExpensesType!.Name,
|
||||
PaymentModeName = e.PaymentMode!.Name,
|
||||
ProjectName = e.Project!.Name,
|
||||
CreatedByName = $"{e.CreatedBy!.FirstName} {e.CreatedBy.LastName}",
|
||||
ReviewedByName = e.ReviewedBy != null ? $"{e.ReviewedBy.FirstName} {e.ReviewedBy.LastName}" : null,
|
||||
ApprovedByName = e.ApprovedBy != null ? $"{e.ApprovedBy.FirstName} {e.ApprovedBy.LastName}" : null,
|
||||
ProcessedByName = e.ProcessedBy != null ? $"{e.ProcessedBy.FirstName} {e.ProcessedBy.LastName}" : null,
|
||||
PaidByName = e.PaidBy != null ? $"{e.PaidBy.FirstName} {e.PaidBy.LastName}" : null
|
||||
})
|
||||
.OrderByDescending(x => x.TransactionDate)
|
||||
var expenses = await baseQuery
|
||||
.ToListAsync(); // Single round-trip; no Include needed for this shape
|
||||
|
||||
var draftExpenses = expenses.Where(e => e.StatusId == Draft && e.CreatedById == loggedInEmployee.Id).ToList();
|
||||
var reviewExpenses = expenses.Where(e => (hasReviewPermission || e.CreatedById == loggedInEmployee.Id) && e.StatusId == Review).ToList();
|
||||
var approveExpenses = expenses.Where(e => (hasApprovePermission || e.CreatedById == loggedInEmployee.Id) && e.StatusId == Approve).ToList();
|
||||
var processPendingExpenses = expenses.Where(e => (hasProcessPermission || e.CreatedById == loggedInEmployee.Id) && e.StatusId == ProcessPending).ToList();
|
||||
var submitedExpenses = expenses.Where(e => e.StatusId != Draft && e.CreatedById == loggedInEmployee.Id).ToList();
|
||||
|
||||
if (hasManagePermission)
|
||||
{
|
||||
var response = new
|
||||
{
|
||||
Draft = new
|
||||
{
|
||||
Count = draftExpenses.Count,
|
||||
TotalAmount = draftExpenses.Sum(e => e.Amount)
|
||||
},
|
||||
ReviewPending = new
|
||||
{
|
||||
Count = reviewExpenses.Count,
|
||||
TotalAmount = reviewExpenses.Sum(e => e.Amount)
|
||||
},
|
||||
ApprovePending = new
|
||||
{
|
||||
Count = approveExpenses.Count,
|
||||
TotalAmount = approveExpenses.Sum(e => e.Amount)
|
||||
},
|
||||
ProcessPending = new
|
||||
{
|
||||
Count = processPendingExpenses.Count,
|
||||
TotalAmount = processPendingExpenses.Sum(e => e.Amount)
|
||||
},
|
||||
Submited = new
|
||||
{
|
||||
Count = submitedExpenses.Count,
|
||||
TotalAmount = submitedExpenses.Sum(e => e.Amount)
|
||||
}
|
||||
};
|
||||
_logger.LogInfo(
|
||||
"GetPendingExpenseListAsync completed. TenantId={TenantId}, Count={Count}",
|
||||
tenantId, response.Count); // [Completion Log]
|
||||
"GetPendingExpenseListAsync completed. TenantId={TenantId}",
|
||||
tenantId); // [Completion Log]
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending Expenses fetched successfully", 200)); // [Success Response]
|
||||
}
|
||||
else
|
||||
{
|
||||
var response = new
|
||||
{
|
||||
Draft = new
|
||||
{
|
||||
Count = draftExpenses.Count
|
||||
},
|
||||
ReviewPending = new
|
||||
{
|
||||
Count = reviewExpenses.Count
|
||||
},
|
||||
ApprovePending = new
|
||||
{
|
||||
Count = approveExpenses.Count
|
||||
},
|
||||
ProcessPending = new
|
||||
{
|
||||
Count = processPendingExpenses.Count
|
||||
},
|
||||
Submited = new
|
||||
{
|
||||
Count = submitedExpenses.Count
|
||||
}
|
||||
};
|
||||
_logger.LogInfo(
|
||||
"GetPendingExpenseListAsync completed. TenantId={TenantId}",
|
||||
tenantId); // [Completion Log]
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending Expenses fetched successfully", 200)); // [Success Response]
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_logger.LogWarning("GetPendingExpenseListAsync canceled by client. TenantId={TenantId}", tenantId); // [Cancel Log]
|
||||
|
Loading…
x
Reference in New Issue
Block a user