// 📁 Services/CertificationService.cs using vendorApproverBackend.Data; using vendorApproverBackend.Entities; using vendorApproverBackend.Enums; using vendorApproverBackend.Responses; using Microsoft.EntityFrameworkCore; using vendorApproverBackend.Dtos; public class CertificationService { private readonly DataContext _context; public CertificationService(DataContext context) { _context = context; } private async Task GenerateCertificationNumber() { long totalCount = await _context.Certifications.LongCountAsync(); return $"C-{totalCount + 1}"; } public async Task GenerateCertificate(PrequalificationRequest pqRequest, User currentUser) { if (pqRequest.Certification != null) { throw new InvalidOperationException($"Certification already exists for PrequalificationRequest ID: {pqRequest.Id}"); } var generalInfo = pqRequest.GeneralInformation ?? throw new InvalidOperationException("GeneralInformation must be present."); var vendor = pqRequest.Vendor ?? throw new InvalidOperationException("Vendor must be included."); var vendorUser = vendor.User ?? throw new InvalidOperationException("Vendor User must be included."); DateTime issueDate = DateTime.UtcNow; DateTime expiryDate = issueDate.AddYears(3); CertificationStatus status = expiryDate > issueDate ? CertificationStatus.ACTIVE : CertificationStatus.EXPIRED; var newCertification = new Certification { CertificationNumber = await GenerateCertificationNumber(), SupplierName = vendor.RepresentativeName, SupplierId = vendorUser.Id, CertificationType = generalInfo.ProductType, IssueDate = issueDate, ExpiryDate = expiryDate, Status = status, VerifiedById = currentUser.Id, PrequalificationRequestId = pqRequest.Id, }; _context.Certifications.Add(newCertification); return newCertification; } /* public async Task> GetCertificationsByCriteria( int page, int size, long? requestId, CertificationStatus? status, string? supplierName, long? vendorId) { if (page < 0) page = 0; if (size <= 0) size = 5; IQueryable query = _context.Certifications .Include(c => c.VerifiedBy) .Include(c => c.PrequalificationRequest); if (requestId.HasValue && requestId.Value > 0) { query = query.Where(c => c.PrequalificationRequestId == requestId.Value); } if (status.HasValue) { query = query.Where(c => c.Status == status.Value); } if (!string.IsNullOrWhiteSpace(supplierName)) { string searchName = supplierName.ToLower(); query = query.Where(c => c.SupplierName.ToLower().Contains(searchName)); } if (vendorId.HasValue && vendorId.Value > 0) { query = query.Where(c => c.PrequalificationRequest.VendorId == vendorId.Value); } query = query.OrderByDescending(c => c.Timestamp); var totalCount = await query.LongCountAsync(); var totalCountInt = (int)totalCount; var items = await query .Skip(page * size) .Take(size) .ToListAsync(); return new PagedResult( items, totalCountInt, page, size ); } */ public async Task> GetCertificationsByCriteria( int page, int size, long? requestId, CertificationStatus? status, string? supplierName, long? vendorId) { if (page < 0) page = 0; if (size <= 0) size = 5; IQueryable query = _context.Certifications .Include(c => c.VerifiedBy) .Include(c => c.PrequalificationRequest) .Include(c => c.PrequalificationRequest) .ThenInclude(p => p.AssignedTo) .Include(c => c.PrequalificationRequest) .ThenInclude(p => p.Inspectors) .Include(c => c.RequestRenews) .ThenInclude(r => r.ExpiredProductCertificateFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.ReferenceOrdersFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.ApprovedDesignFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.UpdateTDSFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.Signature) .Include(c => c.RequestRenews) .ThenInclude(r => r.UpdatedVendorData) .Include(c => c.RequestRenews) .ThenInclude(r => r.TdcDocument) .Include(c => c.RequestRenews) .ThenInclude(r => r.OfficialLetterFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.PerformanceLetters) .Include(c => c.RequestRenews) .ThenInclude(r => r.ManagerRenewFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.AssignedTo) .Include(c => c.RequestRenews) .ThenInclude(r => r.ValidAgencyAgreementFile) .Include(c => c.RequestRenews) .ThenInclude(r => r.Part2Evaluation) .Include(c => c.RequestRenews) .ThenInclude(r => r.Part3Decision) .ThenInclude(d => d.SupportingDocument); // --- Filtering Logic (Remains the same) --- if (requestId.HasValue && requestId.Value > 0) query = query.Where(c => c.PrequalificationRequestId == requestId.Value); if (status.HasValue) query = query.Where(c => c.Status == status.Value); if (!string.IsNullOrWhiteSpace(supplierName)) query = query.Where(c => c.SupplierName.ToLower().Contains(supplierName.ToLower())); if (vendorId.HasValue && vendorId.Value > 0) query = query.Where(c => c.PrequalificationRequest.VendorId == vendorId.Value); query = query.OrderByDescending(c => c.Timestamp); var totalCount = await query.LongCountAsync(); var items = await query .Skip(page * size) .Take(size) .ToListAsync(); // --- Mapping to DTO --- var dtos = items.Select(c => new CertificationDto { Id = c.Id, CertificationNumber = c.CertificationNumber, SupplierName = c.SupplierName, SupplierId = c.SupplierId, CertificationType = c.CertificationType, IssueDate = c.IssueDate, ExpiryDate = c.ExpiryDate, Status = c.Status, VerifiedById = c.VerifiedById, VerifiedBy = c.VerifiedBy, PrequalificationRequestId = c.PrequalificationRequestId, PrequalificationRequest = c.PrequalificationRequest, AssignedTo = c.PrequalificationRequest?.AssignedTo, Inspectors = c.PrequalificationRequest?.Inspectors?.ToList() ?? new List(), Timestamp = c.Timestamp, RequiresReinspection = c.RequiresReinspection, RequestRenews = c.RequestRenews.ToList() // Fully populated with files/signatures }).ToList(); return new PagedResult(dtos, (int)totalCount, page, size); } public async Task GetCertificationByIdAsync(long id) { return await _context.Certifications .Include(c => c.PrequalificationRequest) .Include(c => c.VerifiedBy) .FirstOrDefaultAsync(c => c.Id == id); } public async Task UpdateCertificationStatusAsync(long id, CertificationStatus newStatus) { var certification = await _context.Certifications.FindAsync(id); if (certification == null) { return null; } certification.Status = newStatus; // Optional: If you want to update the timestamp whenever the status changes certification.Timestamp = DateTime.UtcNow; await _context.SaveChangesAsync(); return certification; } }