using CPRNIMS.Domain.Contracts.Reports; using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Dto.Inventory.Reports; using Dapper; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; namespace CPRNIMS.Infrastructure.Reports { public class ReportDataService : IReportDataService { private readonly NonInventoryDbContext _context; public ReportDataService(NonInventoryDbContext context) => _context = context; private const string MainSql = """ SELECT R.RISNo, PR.PRNo, R.QtyIssued, R.IssuedTo, CASE R.Status WHEN 0 THEN 'Draft' WHEN 1 THEN 'Approved' WHEN 2 THEN 'Cancelled' ELSE 'Unknown' END AS StatusLabel, CreatedBy.CreatedBy, ApprovedBy.ApprovedBy, R.ApprovedDate, R.CreatedDate, D.DisciplineName, PRD.ItemName, PRD.ItemNo, IV.QtyIn, IV.QtyOut, IV.QtyOnHand, DEP.Department AS DepartmentName, ISNULL(MRS_AGG.TotalReturned, 0) AS TotalReturned, ISNULL(MRS_AGG.MRSCount, 0) AS MRSCount, R.QtyIssued - ISNULL(MRS_AGG.TotalReturned, 0) AS NetIssued FROM dbo.RIS R INNER JOIN dbo.Disciplines D ON R.DisciplineId = D.DisciplineId INNER JOIN dbo.Inventory IV ON R.InventoryId = IV.InventoryId AND IV.IsActive = 1 LEFT JOIN dbo.Lot L ON IV.LotId = L.LotId OUTER APPLY (SELECT U.FullName ApprovedBy FROM dbo.Users U WHERE R.ApprovedBy = U.UserName) ApprovedBy OUTER APPLY (SELECT U2.FullName CreatedBy FROM dbo.Users U2 WHERE R.CreatedBy = U2.UserName) CreatedBy INNER JOIN Users U ON IV.UserId = U.Id LEFT JOIN dbo.Departments DEP ON U.DepartmentId = DEP.DepartmentId LEFT JOIN dbo.PRDetails PRD ON R.PRDetailId = PRD.PRDetailsId AND PRD.IsActive = 1 LEFT JOIN dbo.PR PR ON PRD.PRId = PR.PRId AND PR.IsActive = 1 LEFT JOIN ( SELECT RISId, COUNT(*) AS MRSCount, SUM(QtyReturned) AS TotalReturned FROM dbo.MRS WHERE Status != 2 GROUP BY RISId ) MRS_AGG ON R.RISId = MRS_AGG.RISId WHERE R.Status != 2 AND R.CreatedDate >= @DateFrom AND R.CreatedDate < DATEADD(DAY, 1, @DateTo) ORDER BY R.CreatedDate DESC, R.RISNo ASC; """; private const string DisciplineSql = """ SELECT D.DisciplineName, COUNT(*) AS SlipCount FROM dbo.RIS R INNER JOIN dbo.Disciplines D ON R.DisciplineId = D.DisciplineId WHERE R.Status != 2 AND R.CreatedDate >= @DateFrom AND R.CreatedDate < DATEADD(DAY, 1, @DateTo) GROUP BY D.DisciplineName ORDER BY SlipCount DESC; """; private const string RecipientsSql = """ SELECT TOP 5 R.IssuedTo AS Name, COUNT(*) AS SlipCount, SUM(IV.QtyOut) AS QtyOut FROM dbo.RIS R INNER JOIN dbo.Inventory IV ON R.InventoryId = IV.InventoryId AND IV.IsActive = 1 WHERE R.Status != 2 AND R.CreatedDate >= @DateFrom AND R.CreatedDate < DATEADD(DAY, 1, @DateTo) GROUP BY R.IssuedTo ORDER BY COUNT(*) DESC; """; public List GetMain(DateTime dateFrom, DateTime dateTo) => Query(MainSql, dateFrom, dateTo); public List GetDisciplines(DateTime dateFrom, DateTime dateTo) => Query(DisciplineSql, dateFrom, dateTo); public List GetRecipients(DateTime dateFrom, DateTime dateTo) => Query(RecipientsSql, dateFrom, dateTo); private List Query(string sql, DateTime from, DateTime to) { using var conn = new SqlConnection(_context.Database.GetConnectionString()); return conn.Query(sql, new { DateFrom = from, DateTo = to }).ToList(); } } }