using Microsoft.EntityFrameworkCore; using vendorApproverBackend.Data; using vendorApproverBackend.Entities; using vendorApproverBackend.Requests; using vendorApproverBackend.Responses; using vendorApproverBackend.Enums; using vendorApproverBackend.Interfaces; using System.Net; using Azure.Core; namespace vendorApproverBackend.Services { public class PrequalificationRequestService { private readonly DataContext _context; private readonly UserService _userService; private readonly ProductService _productService; private readonly INotificationService _notificationService; private readonly CertificationService _certificationService; private readonly IEmailService _emailService; private readonly ILogger _logger; public PrequalificationRequestService(DataContext context, UserService userService, IEmailService emailService, ProductService productService, CertificationService certificationService, INotificationService notificationService, ILogger logger) { _context = context; _userService = userService; _productService = productService; _certificationService = certificationService; _notificationService = notificationService; _emailService = emailService; _logger = logger; } /* public async Task CreateRequestAsync(long vendorId, AddPrequalificationRequestRequest dto) { var vendor = await _context.Vendors.FindAsync(vendorId); if (vendor == null) { throw new Exception("Vendor not found."); } var newRequest = new PrequalificationRequest { VendorId = vendorId, Status = RequestStatus.DRAFT, SubmissionDate = DateTime.UtcNow, GeneralInformation = dto.GeneralInformation, VendorResources = dto.VendorResources, FinancialStanding = dto.FinancialStanding, ExperienceAndAfterSales = dto.ExperienceAndAfterSales, QualityHSERisk = dto.QualityHSERisk, TypeTest = dto.TypeTest, EquipmentGeneralArrangement = dto.EquipmentGeneralArrangement, Compliance = dto.Compliance, Declaration = dto.Declaration }; try { _context.PrequalificationRequests.Add(newRequest); await _context.SaveChangesAsync(); await SendNewRequestNotificationToAdmins(newRequest, vendor); return newRequest; } catch (DbUpdateException dbEx) { _logger.LogError("DbUpdateException: {Message}", dbEx.Message); _logger.LogError("Inner Exception: {InnerMessage}", dbEx.InnerException?.Message); _logger.LogError("Stack Trace: {StackTrace}", dbEx.StackTrace); if (dbEx.InnerException != null) { _logger.LogError("Full Inner Exception: {FullException}", dbEx.InnerException.ToString()); } throw new Exception($"Database error: {dbEx.InnerException?.Message ?? dbEx.Message}", dbEx); } catch (Exception ex) { _logger.LogError("General Exception: {Message}", ex.Message); _logger.LogError("Full Exception: {FullException}", ex.ToString()); throw; } } */ public async Task CreateRequestAsync(long vendorId, AddPrequalificationRequestRequest dto) { // 1. Verify Vendor exists var vendor = await _context.Vendors.FindAsync(vendorId); if (vendor == null) { throw new Exception("Vendor not found."); } // Start a transaction to ensure both operations succeed or fail together using var transaction = await _context.Database.BeginTransactionAsync(); try { // 2. Map DTO to the new PrequalificationRequest Entity var newRequest = new PrequalificationRequest { VendorId = vendorId, // Status = RequestStatus.DRAFT, SubmissionDate = DateTime.UtcNow, GeneralInformation = dto.GeneralInformation, VendorResources = dto.VendorResources, FinancialStanding = dto.FinancialStanding, ExperienceAndAfterSales = dto.ExperienceAndAfterSales, QualityHSERisk = dto.QualityHSERisk, TypeTest = dto.TypeTest, EquipmentGeneralArrangement = dto.EquipmentGeneralArrangement, Compliance = dto.Compliance, Declaration = dto.Declaration }; if (dto.Status != null) { // if passed status differnet from draft and submitted if (dto.Status != RequestStatus.DRAFT && dto.Status != RequestStatus.SUBMITTED && dto.Status != RequestStatus.UNDER_REVIEW) { newRequest.Status = RequestStatus.DRAFT; } else { newRequest.Status = dto.Status.Value; } } else { newRequest.Status = RequestStatus.DRAFT; } // 3. Save the new PQ Request to get its ID _context.PrequalificationRequests.Add(newRequest); await _context.SaveChangesAsync(); // 4. If a Letter ID was provided, link the new Request back to it if (dto.VendorRequestLetterId.HasValue && dto.VendorRequestLetterId.Value > 0) { var letter = await _context.VendorRequestLetters.FindAsync(dto.VendorRequestLetterId.Value); if (letter != null) { // Assign the newly generated ID to the letter letter.CreatedPqRequestId = newRequest.Id; _context.VendorRequestLetters.Update(letter); await _context.SaveChangesAsync(); } else { _logger.LogWarning("VendorRequestLetter with ID {LetterId} not found. Skipping link.", dto.VendorRequestLetterId); } } // 5. Commit everything to the database await transaction.CommitAsync(); // 6. Trigger notification await SendNewRequestNotificationToAdmins(newRequest, vendor); return newRequest; } catch (DbUpdateException dbEx) { await transaction.RollbackAsync(); _logger.LogError("Database error: {Message}", dbEx.InnerException?.Message ?? dbEx.Message); throw new Exception($"Database error: {dbEx.InnerException?.Message ?? dbEx.Message}", dbEx); } catch (Exception ex) { await transaction.RollbackAsync(); _logger.LogError("General Exception: {Message}", ex.Message); throw; } } private async Task SendNewRequestNotificationToAdmins(PrequalificationRequest newRequest, Vendor vendor) { try { var adminUserIds = await _userService.GetAdminUserIdsAsync(); if (adminUserIds.Any()) { var notification = new NotificationModel { SenderId = vendor.UserId, Subject = "New PQ-Request Created", Content = $"New PQ-request added by {vendor.RepresentativeName}", Action = Action.NEW_Pq_REQUEST, ActionId = newRequest.Id, LogUrl = "", Status = states.WAITING }; await _notificationService.SendNotificationToListOfUsers(adminUserIds, notification); } else { _logger.LogWarning("No admin users found to send notification to"); } } catch (Exception ex) { _logger.LogError(ex, "Failed to send notification for new PQ request {RequestId}", newRequest.Id); } } /* public async Task UpdateRequestAsync(long requestId, AddPrequalificationRequestRequest dto) { //var requestFromDb = await _context.PrequalificationRequests.FindAsync(requestId); var requestFromDb = await _context.PrequalificationRequests .Include(r => r.GeneralInformation) .ThenInclude(gi => gi.LocalOwners) .Include(r => r.GeneralInformation) .ThenInclude(gi => gi.BoardOfDirectors) .Include(r => r.VendorResources) .ThenInclude(vr => vr.StaffDetails) .FirstOrDefaultAsync(r => r.Id == requestId); if (requestFromDb == null) return null; if (dto.GeneralInformation != null) { if (requestFromDb.GeneralInformation == null) requestFromDb.GeneralInformation = new GeneralInformation(); var gi = dto.GeneralInformation; var dbGi = requestFromDb.GeneralInformation; if (gi.FullName != null) dbGi.FullName = gi.FullName; if (gi.ShortName != null) dbGi.ShortName = gi.ShortName; if (gi.DateEstablished != null) dbGi.DateEstablished = gi.DateEstablished; if (gi.OriginCountry != null) dbGi.OriginCountry = gi.OriginCountry; if (gi.VendorGpsCoordinates != null) dbGi.VendorGpsCoordinates = gi.VendorGpsCoordinates; if (gi.VendorWebsite != null) dbGi.VendorWebsite = gi.VendorWebsite; if (gi.OfficeLocation != null) dbGi.OfficeLocation = gi.OfficeLocation; if (gi.GccCountryName != null) dbGi.GccCountryName = gi.GccCountryName; if (gi.OtherCountryName != null) dbGi.OtherCountryName = gi.OtherCountryName; if (gi.OmanStreet != null) dbGi.OmanStreet = gi.OmanStreet; if (gi.OmanPoBox != null) dbGi.OmanPoBox = gi.OmanPoBox; if (gi.OmanTel != null) dbGi.OmanTel = gi.OmanTel; if (gi.OmanFax != null) dbGi.OmanFax = gi.OmanFax; if (gi.HqStreet != null) dbGi.HqStreet = gi.HqStreet; if (gi.HqPoBox != null) dbGi.HqPoBox = gi.HqPoBox; if (gi.HqTel != null) dbGi.HqTel = gi.HqTel; if (gi.HqFax != null) dbGi.HqFax = gi.HqFax; if (gi.HqEmail != null) dbGi.HqEmail = gi.HqEmail; if (gi.FactoryStreet != null) dbGi.FactoryStreet = gi.FactoryStreet; if (gi.FactoryPoBox != null) dbGi.FactoryPoBox = gi.FactoryPoBox; if (gi.FactoryTel != null) dbGi.FactoryTel = gi.FactoryTel; if (gi.FactoryFax != null) dbGi.FactoryFax = gi.FactoryFax; if (gi.FactoryEmail != null) dbGi.FactoryEmail = gi.FactoryEmail; if (gi.SalesStreet != null) dbGi.SalesStreet = gi.SalesStreet; if (gi.SalesPoBox != null) dbGi.SalesPoBox = gi.SalesPoBox; if (gi.SalesTel != null) dbGi.SalesTel = gi.SalesTel; if (gi.SalesFax != null) dbGi.SalesFax = gi.SalesFax; if (gi.SalesEmail != null) dbGi.SalesEmail = gi.SalesEmail; if (gi.Category != null) dbGi.Category = gi.Category; if (gi.Subcategory != null) dbGi.Subcategory = gi.Subcategory; if (gi.ProductName != null) dbGi.ProductName = gi.ProductName; if (gi.ProductCity != null) dbGi.ProductCity = gi.ProductCity; if (gi.ProductCountry != null) dbGi.ProductCountry = gi.ProductCountry; if (gi.ProductType != null) dbGi.ProductType = gi.ProductType; if (gi.ProductDesc != null) dbGi.ProductDesc = gi.ProductDesc; if (gi.LocalOwners != null) { dbGi.LocalOwners.Clear(); dbGi.LocalOwners.AddRange(gi.LocalOwners); } dbGi.IsBranchInOman = gi.IsBranchInOman; if (gi.BoardOfDirectors != null) { dbGi.BoardOfDirectors.Clear(); dbGi.BoardOfDirectors.AddRange(gi.BoardOfDirectors); } if (gi.AgentNames != null) dbGi.AgentNames = gi.AgentNames; if (gi.CommercialRegNumber != null) dbGi.CommercialRegNumber = gi.CommercialRegNumber; if (gi.AgentContactPerson != null) dbGi.AgentContactPerson = gi.AgentContactPerson; if (gi.AgentDesignation != null) dbGi.AgentDesignation = gi.AgentDesignation; if (gi.RegisteredHeadOffice != null) dbGi.RegisteredHeadOffice = gi.RegisteredHeadOffice; if (gi.GpsCoordinates != null) dbGi.GpsCoordinates = gi.GpsCoordinates; if (gi.AgentTel != null) dbGi.AgentTel = gi.AgentTel; if (gi.AgentFax != null) dbGi.AgentFax = gi.AgentFax; if (gi.AgentEmail != null) dbGi.AgentEmail = gi.AgentEmail; if (gi.AgentWebsite != null) dbGi.AgentWebsite = gi.AgentWebsite; if (gi.ContactPersons != null) { dbGi.ContactPersons.Clear(); dbGi.ContactPersons.AddRange(gi.ContactPersons); } if (gi.AuthorizedSignatories != null) { dbGi.AuthorizedSignatories.Clear(); dbGi.AuthorizedSignatories.AddRange(gi.AuthorizedSignatories); } if (gi.OfficialAgencySubmitted != null) dbGi.OfficialAgencySubmitted = gi.OfficialAgencySubmitted; if (gi.AuthorizedPersonsSubmitted != null) dbGi.AuthorizedPersonsSubmitted = gi.AuthorizedPersonsSubmitted; if (gi.CertificatesAndLicenses != null) { if (dbGi.CertificatesAndLicenses == null) dbGi.CertificatesAndLicenses = new CertificatesAndLicenses(); var cl = gi.CertificatesAndLicenses; var dbCl = dbGi.CertificatesAndLicenses; if (cl.LocalSupportId != null) dbCl.LocalSupportId = cl.LocalSupportId; if (cl.SupportTeamCVsIds != null) { dbCl.SupportTeamCVsIds.Clear(); dbCl.SupportTeamCVsIds.AddRange(cl.SupportTeamCVsIds); } if (cl.TradeLicense != null) { if (dbCl.TradeLicense == null) dbCl.TradeLicense = new TradeLicense(); if (cl.TradeLicense.RegistrationNo != null) dbCl.TradeLicense.RegistrationNo = cl.TradeLicense.RegistrationNo; if (cl.TradeLicense.RegistrationDate != null) dbCl.TradeLicense.RegistrationDate = cl.TradeLicense.RegistrationDate; if (cl.TradeLicense.ExpiryDate != null) dbCl.TradeLicense.ExpiryDate = cl.TradeLicense.ExpiryDate; if (cl.TradeLicense.DocumentId != null) dbCl.TradeLicense.DocumentId = cl.TradeLicense.DocumentId; } if (cl.ChamberMembership != null) { if (dbCl.ChamberMembership == null) dbCl.ChamberMembership = new ChamberMembership(); if (cl.ChamberMembership.RegistrationNo != null) dbCl.ChamberMembership.RegistrationNo = cl.ChamberMembership.RegistrationNo; if (cl.ChamberMembership.RegistrationDate != null) dbCl.ChamberMembership.RegistrationDate = cl.ChamberMembership.RegistrationDate; if (cl.ChamberMembership.ExpiryDate != null) dbCl.ChamberMembership.ExpiryDate = cl.ChamberMembership.ExpiryDate; if (cl.ChamberMembership.DocumentId != null) dbCl.ChamberMembership.DocumentId = cl.ChamberMembership.DocumentId; } if (cl.IndustrialLicenses != null) { dbCl.IndustrialLicenses.Clear(); dbCl.IndustrialLicenses.AddRange(cl.IndustrialLicenses); } } if (gi.AssociatedCompanies != null) { dbGi.AssociatedCompanies.Clear(); dbGi.AssociatedCompanies.AddRange(gi.AssociatedCompanies); } } if (dto.VendorResources != null) { if (requestFromDb.VendorResources == null) requestFromDb.VendorResources = new VendorResources(); var vr = dto.VendorResources; var dbVr = requestFromDb.VendorResources; if (vr.ProductionCapacity != null) dbVr.ProductionCapacity = vr.ProductionCapacity; if (vr.TotalFactoryArea != null) dbVr.TotalFactoryArea = vr.TotalFactoryArea; if (vr.TotalBuiltUpArea != null) dbVr.TotalBuiltUpArea = vr.TotalBuiltUpArea; if (vr.DepartmentBuildings != null) dbVr.DepartmentBuildings = vr.DepartmentBuildings; if (vr.OrgChartFileId != null) dbVr.OrgChartFileId = vr.OrgChartFileId; if (vr.TechSupportChartFileId != null) dbVr.TechSupportChartFileId = vr.TechSupportChartFileId; if (vr.StaffDetails != null) { dbVr.StaffDetails.Clear(); dbVr.StaffDetails.AddRange(vr.StaffDetails); } if (vr.QualifiedStaff != null) { dbVr.QualifiedStaff.Clear(); dbVr.QualifiedStaff.AddRange(vr.QualifiedStaff); } dbVr.OrgChartManufacturer = vr.OrgChartManufacturer; dbVr.OrgChartCorporate = vr.OrgChartCorporate; dbVr.OrgChartFactoryTechSupport = vr.OrgChartFactoryTechSupport; dbVr.OrgChartLocalTechSupport = vr.OrgChartLocalTechSupport; if (vr.OrgChartManufacturerFileId != null) dbVr.OrgChartManufacturerFileId = vr.OrgChartManufacturerFileId; if (vr.OrgChartCorporateFileId != null) dbVr.OrgChartCorporateFileId = vr.OrgChartCorporateFileId; if (vr.OrgChartFactoryTechSupportFileId != null) dbVr.OrgChartFactoryTechSupportFileId = vr.OrgChartFactoryTechSupportFileId; if (vr.OrgChartLocalTechSupportFileId != null) dbVr.OrgChartLocalTechSupportFileId = vr.OrgChartLocalTechSupportFileId; if (vr.TechnicalItems != null) { dbVr.TechnicalItems.Clear(); dbVr.TechnicalItems.AddRange(vr.TechnicalItems); } if (vr.Applications != null) { dbVr.Applications.Clear(); dbVr.Applications.AddRange(vr.Applications); } if (vr.CommunicationFacilities != null) dbVr.CommunicationFacilities = vr.CommunicationFacilities; if (vr.PlanningProcess != null) dbVr.PlanningProcess = vr.PlanningProcess; if (vr.PlanningMonitoring != null) dbVr.PlanningMonitoring = vr.PlanningMonitoring; if (vr.ProductionPlanning != null) dbVr.ProductionPlanning = vr.ProductionPlanning; if (vr.QualityControlPlanning != null) dbVr.QualityControlPlanning = vr.QualityControlPlanning; if (vr.DesignProcess != null) dbVr.DesignProcess = vr.DesignProcess; if (vr.DesignChangeControl != null) dbVr.DesignChangeControl = vr.DesignChangeControl; if (vr.SoftwareList != null) { dbVr.SoftwareList.Clear(); dbVr.SoftwareList.AddRange(vr.SoftwareList); } if (vr.SupplierApprovalProcess != null) dbVr.SupplierApprovalProcess = vr.SupplierApprovalProcess; if (vr.TransmissionToSuppliers != null) dbVr.TransmissionToSuppliers = vr.TransmissionToSuppliers; if (vr.SupplierReevaluation != null) dbVr.SupplierReevaluation = vr.SupplierReevaluation; if (vr.SupplierQCMeans != null) dbVr.SupplierQCMeans = vr.SupplierQCMeans; if (vr.SupplierListFileId != null) dbVr.SupplierListFileId = vr.SupplierListFileId; if (vr.ProductionProcessControl != null) dbVr.ProductionProcessControl = vr.ProductionProcessControl; if (vr.ProductionSupportFileId != null) dbVr.ProductionSupportFileId = vr.ProductionSupportFileId; if (vr.ProductionAuthority != null) dbVr.ProductionAuthority = vr.ProductionAuthority; if (vr.IdentificationTraceability != null) dbVr.IdentificationTraceability = vr.IdentificationTraceability; if (vr.MaintenanceOfEquipment != null) dbVr.MaintenanceOfEquipment = vr.MaintenanceOfEquipment; if (vr.ProductionQualifiedStaff != null) { dbVr.ProductionQualifiedStaff.Clear(); dbVr.ProductionQualifiedStaff.AddRange(vr.ProductionQualifiedStaff); } if (vr.QualityDocuments != null) { dbVr.QualityDocuments.Clear(); dbVr.QualityDocuments.AddRange(vr.QualityDocuments); } if (vr.StandardManagement != null) dbVr.StandardManagement = vr.StandardManagement; if (vr.InternationalStandards != null) { dbVr.InternationalStandards.Clear(); dbVr.InternationalStandards.AddRange(vr.InternationalStandards); } if (vr.QualityAuthority != null) dbVr.QualityAuthority = vr.QualityAuthority; if (vr.QualityQualifiedStaff != null) { dbVr.QualityQualifiedStaff.Clear(); dbVr.QualityQualifiedStaff.AddRange(vr.QualityQualifiedStaff); } if (vr.QualityTraceability != null) dbVr.QualityTraceability = vr.QualityTraceability; if (vr.QcMethods != null) dbVr.QcMethods = vr.QcMethods; if (vr.QcPlans != null) dbVr.QcPlans = vr.QcPlans; if (vr.QcPlanFileId != null) dbVr.QcPlanFileId = vr.QcPlanFileId; if (vr.QcProcedures != null) dbVr.QcProcedures = vr.QcProcedures; if (vr.QcProceduresFileId != null) dbVr.QcProceduresFileId = vr.QcProceduresFileId; if (vr.ReceiptMaterials != null) dbVr.ReceiptMaterials = vr.ReceiptMaterials; if (vr.InventoryManagement != null) dbVr.InventoryManagement = vr.InventoryManagement; if (vr.NonConformityControl != null) dbVr.NonConformityControl = vr.NonConformityControl; if (vr.FailureStats != null) dbVr.FailureStats = vr.FailureStats; if (vr.PackagingTransport != null) dbVr.PackagingTransport = vr.PackagingTransport; if (vr.WasteManagement != null) dbVr.WasteManagement = vr.WasteManagement; } if (dto.FinancialStanding != null) { if (requestFromDb.FinancialStanding == null) requestFromDb.FinancialStanding = new FinancialStanding(); var fs = dto.FinancialStanding; var dbFs = requestFromDb.FinancialStanding; if (fs.VendorFullName != null) dbFs.VendorFullName = fs.VendorFullName; if (fs.AuditReportsIds != null) { dbFs.AuditReportsIds.Clear(); dbFs.AuditReportsIds.AddRange(fs.AuditReportsIds); } if (fs.AuditorName != null) dbFs.AuditorName = fs.AuditorName; if (fs.AuditorAddress != null) dbFs.AuditorAddress = fs.AuditorAddress; if (fs.EBITDA_2024 != null) dbFs.EBITDA_2024 = fs.EBITDA_2024; if (fs.EBITDA_2022 != null) dbFs.EBITDA_2022 = fs.EBITDA_2022; if (fs.EBITDA_2023 != null) dbFs.EBITDA_2023 = fs.EBITDA_2023; if (fs.NetProfitMargin_2024 != null) dbFs.NetProfitMargin_2024 = fs.NetProfitMargin_2024; if (fs.NetProfitMargin_2022 != null) dbFs.NetProfitMargin_2022 = fs.NetProfitMargin_2022; if (fs.NetProfitMargin_2023 != null) dbFs.NetProfitMargin_2023 = fs.NetProfitMargin_2023; if (fs.CurrentRatio_2024 != null) dbFs.CurrentRatio_2024 = fs.CurrentRatio_2024; if (fs.CurrentRatio_2022 != null) dbFs.CurrentRatio_2022 = fs.CurrentRatio_2022; if (fs.CurrentRatio_2023 != null) dbFs.CurrentRatio_2023 = fs.CurrentRatio_2023; if (fs.CashFlowRatio_2024 != null) dbFs.CashFlowRatio_2024 = fs.CashFlowRatio_2024; if (fs.CashFlowRatio_2022 != null) dbFs.CashFlowRatio_2022 = fs.CashFlowRatio_2022; if (fs.CashFlowRatio_2023 != null) dbFs.CashFlowRatio_2023 = fs.CashFlowRatio_2023; if (fs.DebtEquityRatio_2024 != null) dbFs.DebtEquityRatio_2024 = fs.DebtEquityRatio_2024; if (fs.DebtEquityRatio_2022 != null) dbFs.DebtEquityRatio_2022 = fs.DebtEquityRatio_2022; if (fs.DebtEquityRatio_2023 != null) dbFs.DebtEquityRatio_2023 = fs.DebtEquityRatio_2023; if (fs.Bankers != null) { dbFs.Bankers.Clear(); dbFs.Bankers.AddRange(fs.Bankers); } } if (dto.ExperienceAndAfterSales != null) { if (requestFromDb.ExperienceAndAfterSales == null) requestFromDb.ExperienceAndAfterSales = new ExperienceAndAfterSales(); var eas = dto.ExperienceAndAfterSales; var dbEas = requestFromDb.ExperienceAndAfterSales; // ... (ClientReferences, ManufacturerProductInfo, ClientRefDate updates remain the same) if (eas.ClientReferences != null) { dbEas.ClientReferences.Clear(); dbEas.ClientReferences.AddRange(eas.ClientReferences); } if (eas.ManufacturerProductInfo != null) dbEas.ManufacturerProductInfo = eas.ManufacturerProductInfo; if (eas.ClientRefDate != null) dbEas.ClientRefDate = eas.ClientRefDate; dbEas.AfterSalesReport = eas.AfterSalesReport; if (eas.WarrantyCertificateFile != null) { dbEas.WarrantyCertificateFileId = eas.WarrantyCertificateFile.Id; } else { dbEas.WarrantyCertificateFileId = null; } dbEas.IssueTrackingSystem = eas.IssueTrackingSystem; } if (dto.QualityHSERisk != null) { if (requestFromDb.QualityHSERisk == null) requestFromDb.QualityHSERisk = new QualityHSERisk(); var qhr = dto.QualityHSERisk; var dbQhr = requestFromDb.QualityHSERisk; if (qhr.Certificates != null) { dbQhr.Certificates.Clear(); dbQhr.Certificates.AddRange(qhr.Certificates); } dbQhr.HasQualitySystem = qhr.HasQualitySystem; dbQhr.HasQaManual = qhr.HasQaManual; dbQhr.HasQaProcedures = qhr.HasQaProcedures; dbQhr.QaSystemMeetsStandard = qhr.QaSystemMeetsStandard; if (qhr.QaSystemDetails != null) dbQhr.QaSystemDetails = qhr.QaSystemDetails; dbQhr.QaSystemApprovedByAgency = qhr.QaSystemApprovedByAgency; if (qhr.ApprovedAgencyNames != null) dbQhr.ApprovedAgencyNames = qhr.ApprovedAgencyNames; dbQhr.HasAuditSchedule = qhr.HasAuditSchedule; dbQhr.HasHSEManual = qhr.HasHSEManual; dbQhr.HseMeetsStandard = qhr.HseMeetsStandard; if (qhr.EngineeringStandards != null) dbQhr.EngineeringStandards = qhr.EngineeringStandards; if (qhr.RiskManagement != null) dbQhr.RiskManagement = qhr.RiskManagement; dbQhr.HasTrainingFacility = qhr.HasTrainingFacility; if (qhr.TrainingDescription != null) dbQhr.TrainingDescription = qhr.TrainingDescription; if (qhr.QaSummary != null) { dbQhr.QaSummary.Clear(); dbQhr.QaSummary.AddRange(qhr.QaSummary); } if (qhr.CertInProcessDetails != null) dbQhr.CertInProcessDetails = qhr.CertInProcessDetails; if (qhr.CertProcessLetterId != null) dbQhr.CertProcessLetterId = qhr.CertProcessLetterId; } if (dto.TypeTest != null) { if (requestFromDb.TypeTest == null) requestFromDb.TypeTest = new TypeTest(); var tt = dto.TypeTest; var dbTt = requestFromDb.TypeTest; if (tt.TestType != null) dbTt.TestType = tt.TestType; dbTt.ThirdPartyReports = tt.ThirdPartyReports; dbTt.ThirdPartyCertificates = tt.ThirdPartyCertificates; if (tt.ThirdPartyReportsFileId != null) dbTt.ThirdPartyReportsFileId = tt.ThirdPartyReportsFileId; if (tt.ThirdPartyCertificatesFileId != null) dbTt.ThirdPartyCertificatesFileId = tt.ThirdPartyCertificatesFileId; dbTt.FactoryOwnLab = tt.FactoryOwnLab; dbTt.Lab17025Accredited = tt.Lab17025Accredited; dbTt.FactoryTestApprovedProcedure = tt.FactoryTestApprovedProcedure; if (tt.FactoryOwnLabFileId != null) dbTt.FactoryOwnLabFileId = tt.FactoryOwnLabFileId; if (tt.Lab17025AccreditedFileId != null) dbTt.Lab17025AccreditedFileId = tt.Lab17025AccreditedFileId; if (tt.FactoryTestApprovedProcedureFileId != null) dbTt.FactoryTestApprovedProcedureFileId = tt.FactoryTestApprovedProcedureFileId; } if (dto.EquipmentGeneralArrangement != null) { if (requestFromDb.EquipmentGeneralArrangement == null) requestFromDb.EquipmentGeneralArrangement = new EquipmentGeneralArrangement(); var ega = dto.EquipmentGeneralArrangement; var dbEga = requestFromDb.EquipmentGeneralArrangement; dbEga.GaDrawingEnclosed = ega.GaDrawingEnclosed; dbEga.TypicalConnectionDrawing = ega.TypicalConnectionDrawing; dbEga.Product3DModel = ega.Product3DModel; if (ega.GaFileId != null) dbEga.GaFileId = ega.GaFileId; if (ega.ConnectionDrawingFileId != null) dbEga.ConnectionDrawingFileId = ega.ConnectionDrawingFileId; if (ega.Product3DModelFileId != null) dbEga.Product3DModelFileId = ega.Product3DModelFileId; } if (dto.Compliance != null) { if (requestFromDb.Compliance == null) requestFromDb.Compliance = new Compliance(); var c = dto.Compliance; var dbC = requestFromDb.Compliance; dbC.GtpSubmitted = c.GtpSubmitted; if (c.GtpSubmittedFileId != null) dbC.GtpSubmittedFileId = c.GtpSubmittedFileId; dbC.ComplianceConfirmed = c.ComplianceConfirmed; if (c.ComplianceConfirmedFileId != null) dbC.ComplianceConfirmedFileId = c.ComplianceConfirmedFileId; if (c.GtpFileId != null) dbC.GtpFileId = c.GtpFileId; } if (dto.Declaration != null) { if (requestFromDb.Declaration == null) requestFromDb.Declaration = new Declaration(); var d = dto.Declaration; var dbD = requestFromDb.Declaration; if (d.FullName != null) dbD.FullName = d.FullName; if (d.Designation != null) dbD.Designation = d.Designation; if (d.OnBehalfOf != null) dbD.OnBehalfOf = d.OnBehalfOf; if (d.SignedDate != null) dbD.SignedDate = d.SignedDate; if (d.PowerOfAttorneyFileId != null) dbD.PowerOfAttorneyFileId = d.PowerOfAttorneyFileId; } requestFromDb.Status = RequestStatus.CONFIRMED; requestFromDb.AdminObservations.Clear(); await _context.SaveChangesAsync(); return requestFromDb; } */ public async Task UpdateRequestAsync(long requestId, AddPrequalificationRequestRequest dto) { var requestFromDb = await _context.PrequalificationRequests .Include(r => r.GeneralInformation) .Include(r => r.VendorResources) .Include(r => r.FinancialStanding) .Include(r => r.ExperienceAndAfterSales) .Include(r => r.QualityHSERisk) .Include(r => r.TypeTest) .Include(r => r.EquipmentGeneralArrangement) .Include(r => r.Compliance) .Include(r => r.Declaration) .FirstOrDefaultAsync(r => r.Id == requestId); if (requestFromDb == null) return null; // ====== STEP 1 ====== if (dto.GeneralInformation != null) { if (requestFromDb.GeneralInformation == null) requestFromDb.GeneralInformation = new GeneralInformation(); var gi = dto.GeneralInformation; var dbGi = requestFromDb.GeneralInformation; if (gi.StepOneApproverComment != null) dbGi.StepOneApproverComment = gi.StepOneApproverComment; if (gi.FullName != null) dbGi.FullName = gi.FullName; if (gi.ShortName != null) dbGi.ShortName = gi.ShortName; if (gi.DateEstablished != null) dbGi.DateEstablished = gi.DateEstablished; if (gi.OriginCountry != null) dbGi.OriginCountry = gi.OriginCountry; if (gi.VendorGpsCoordinates != null) dbGi.VendorGpsCoordinates = gi.VendorGpsCoordinates; if (gi.VendorWebsite != null) dbGi.VendorWebsite = gi.VendorWebsite; if (gi.OfficeLocation != null) dbGi.OfficeLocation = gi.OfficeLocation; if (gi.GccCountryName != null) dbGi.GccCountryName = gi.GccCountryName; if (gi.OtherCountryName != null) dbGi.OtherCountryName = gi.OtherCountryName; if (gi.OmanStreet != null) dbGi.OmanStreet = gi.OmanStreet; if (gi.OmanPoBox != null) dbGi.OmanPoBox = gi.OmanPoBox; if (gi.OmanTel != null) dbGi.OmanTel = gi.OmanTel; if (gi.OmanFax != null) dbGi.OmanFax = gi.OmanFax; if (gi.HqStreet != null) dbGi.HqStreet = gi.HqStreet; if (gi.HqPoBox != null) dbGi.HqPoBox = gi.HqPoBox; if (gi.HqTel != null) dbGi.HqTel = gi.HqTel; if (gi.HqFax != null) dbGi.HqFax = gi.HqFax; if (gi.HqEmail != null) dbGi.HqEmail = gi.HqEmail; if (gi.FactoryStreet != null) dbGi.FactoryStreet = gi.FactoryStreet; if (gi.FactoryPoBox != null) dbGi.FactoryPoBox = gi.FactoryPoBox; if (gi.FactoryTel != null) dbGi.FactoryTel = gi.FactoryTel; if (gi.FactoryFax != null) dbGi.FactoryFax = gi.FactoryFax; if (gi.FactoryEmail != null) dbGi.FactoryEmail = gi.FactoryEmail; if (gi.SalesStreet != null) dbGi.SalesStreet = gi.SalesStreet; if (gi.SalesPoBox != null) dbGi.SalesPoBox = gi.SalesPoBox; if (gi.SalesTel != null) dbGi.SalesTel = gi.SalesTel; if (gi.SalesFax != null) dbGi.SalesFax = gi.SalesFax; if (gi.SalesEmail != null) dbGi.SalesEmail = gi.SalesEmail; if (gi.Category != null) dbGi.Category = gi.Category; if (gi.Subcategory != null) dbGi.Subcategory = gi.Subcategory; if (gi.ProductName != null) dbGi.ProductName = gi.ProductName; if (gi.ProductCity != null) dbGi.ProductCity = gi.ProductCity; if (gi.ProductCountry != null) dbGi.ProductCountry = gi.ProductCountry; if (gi.ProductType != null) dbGi.ProductType = gi.ProductType; if (gi.ProductDesc != null) dbGi.ProductDesc = gi.ProductDesc; if (gi.LocalOwners != null) { dbGi.LocalOwners.Clear(); dbGi.LocalOwners.AddRange(gi.LocalOwners); } dbGi.IsBranchInOman = gi.IsBranchInOman; if (gi.BoardOfDirectors != null) { dbGi.BoardOfDirectors.Clear(); dbGi.BoardOfDirectors.AddRange(gi.BoardOfDirectors); } if (gi.AgentNames != null) dbGi.AgentNames = gi.AgentNames; if (gi.CommercialRegNumber != null) dbGi.CommercialRegNumber = gi.CommercialRegNumber; if (gi.AgentContactPerson != null) dbGi.AgentContactPerson = gi.AgentContactPerson; if (gi.AgentDesignation != null) dbGi.AgentDesignation = gi.AgentDesignation; if (gi.RegisteredHeadOffice != null) dbGi.RegisteredHeadOffice = gi.RegisteredHeadOffice; if (gi.GpsCoordinates != null) dbGi.GpsCoordinates = gi.GpsCoordinates; if (gi.AgentTel != null) dbGi.AgentTel = gi.AgentTel; if (gi.AgentFax != null) dbGi.AgentFax = gi.AgentFax; if (gi.AgentEmail != null) dbGi.AgentEmail = gi.AgentEmail; if (gi.AgentWebsite != null) dbGi.AgentWebsite = gi.AgentWebsite; if (gi.ContactPersons != null) { dbGi.ContactPersons.Clear(); dbGi.ContactPersons.AddRange(gi.ContactPersons); } if (gi.AuthorizedSignatories != null) { dbGi.AuthorizedSignatories.Clear(); dbGi.AuthorizedSignatories.AddRange(gi.AuthorizedSignatories); } if (gi.OfficialAgencySubmitted != null) dbGi.OfficialAgencySubmitted = gi.OfficialAgencySubmitted; if (gi.AuthorizedPersonsSubmitted != null) dbGi.AuthorizedPersonsSubmitted = gi.AuthorizedPersonsSubmitted; if (gi.CertificatesAndLicenses != null) { if (dbGi.CertificatesAndLicenses == null) dbGi.CertificatesAndLicenses = new CertificatesAndLicenses(); var cl = gi.CertificatesAndLicenses; var dbCl = dbGi.CertificatesAndLicenses; if (cl.LocalSupportId != null) dbCl.LocalSupportId = cl.LocalSupportId; if (cl.SupportTeamCVsIds != null) { dbCl.SupportTeamCVsIds.Clear(); dbCl.SupportTeamCVsIds.AddRange(cl.SupportTeamCVsIds); } if (cl.TradeLicense != null) { if (dbCl.TradeLicense == null) dbCl.TradeLicense = new TradeLicense(); if (cl.TradeLicense.RegistrationNo != null) dbCl.TradeLicense.RegistrationNo = cl.TradeLicense.RegistrationNo; if (cl.TradeLicense.RegistrationDate != null) dbCl.TradeLicense.RegistrationDate = cl.TradeLicense.RegistrationDate; if (cl.TradeLicense.ExpiryDate != null) dbCl.TradeLicense.ExpiryDate = cl.TradeLicense.ExpiryDate; if (cl.TradeLicense.DocumentId != null) dbCl.TradeLicense.DocumentId = cl.TradeLicense.DocumentId; } if (cl.ChamberMembership != null) { if (dbCl.ChamberMembership == null) dbCl.ChamberMembership = new ChamberMembership(); if (cl.ChamberMembership.RegistrationNo != null) dbCl.ChamberMembership.RegistrationNo = cl.ChamberMembership.RegistrationNo; if (cl.ChamberMembership.RegistrationDate != null) dbCl.ChamberMembership.RegistrationDate = cl.ChamberMembership.RegistrationDate; if (cl.ChamberMembership.ExpiryDate != null) dbCl.ChamberMembership.ExpiryDate = cl.ChamberMembership.ExpiryDate; if (cl.ChamberMembership.DocumentId != null) dbCl.ChamberMembership.DocumentId = cl.ChamberMembership.DocumentId; } if (cl.IndustrialLicenses != null) { dbCl.IndustrialLicenses.Clear(); dbCl.IndustrialLicenses.AddRange(cl.IndustrialLicenses); } } if (gi.AssociatedCompanies != null) { dbGi.AssociatedCompanies.Clear(); dbGi.AssociatedCompanies.AddRange(gi.AssociatedCompanies); } } // ====== STEP 2 ====== if (dto.VendorResources != null) { if (requestFromDb.VendorResources == null) requestFromDb.VendorResources = new VendorResources(); var vr = dto.VendorResources; var dbVr = requestFromDb.VendorResources; if (vr.StepTwoApproverComment != null) dbVr.StepTwoApproverComment = vr.StepTwoApproverComment; if (vr.ProductionCapacity != null) dbVr.ProductionCapacity = vr.ProductionCapacity; if (vr.TotalFactoryArea != null) dbVr.TotalFactoryArea = vr.TotalFactoryArea; if (vr.TotalBuiltUpArea != null) dbVr.TotalBuiltUpArea = vr.TotalBuiltUpArea; if (vr.DepartmentBuildings != null) dbVr.DepartmentBuildings = vr.DepartmentBuildings; if (vr.OrgChartFileId != null) dbVr.OrgChartFileId = vr.OrgChartFileId; if (vr.TechSupportChartFileId != null) dbVr.TechSupportChartFileId = vr.TechSupportChartFileId; if (vr.StaffDetails != null) { dbVr.StaffDetails.Clear(); dbVr.StaffDetails.AddRange(vr.StaffDetails); } /* if (vr.QualifiedStaff != null) { dbVr.QualifiedStaff.Clear(); dbVr.QualifiedStaff.AddRange(vr.QualifiedStaff); } */ if (vr.QualifiedStaff != null) { // If the database list is empty, just take the new one if (dbVr.QualifiedStaff == null || !dbVr.QualifiedStaff.Any()) { dbVr.QualifiedStaff = vr.QualifiedStaff; } else { // We loop through the incoming list to apply the "null check" logic for (int i = 0; i < vr.QualifiedStaff.Count; i++) { var incoming = vr.QualifiedStaff[i]; // If we have a matching index in the DB, update it if (i < dbVr.QualifiedStaff.Count) { var existing = dbVr.QualifiedStaff[i]; // Update only if not null if (incoming.Qualification != null) existing.Qualification = incoming.Qualification; if (incoming.Number != null) existing.Number = incoming.Number; // NEW ATTRIBUTE LOGIC: Update if not null, otherwise keep existing if (incoming.Designation != null) { existing.Designation = incoming.Designation; } } else { // If the incoming list is longer than the DB list, add the new items dbVr.QualifiedStaff.Add(incoming); } } } } dbVr.OrgChartManufacturer = vr.OrgChartManufacturer; dbVr.OrgChartCorporate = vr.OrgChartCorporate; dbVr.OrgChartFactoryTechSupport = vr.OrgChartFactoryTechSupport; dbVr.OrgChartLocalTechSupport = vr.OrgChartLocalTechSupport; if (vr.OrgChartManufacturerFileId != null) dbVr.OrgChartManufacturerFileId = vr.OrgChartManufacturerFileId; if (vr.OrgChartCorporateFileId != null) dbVr.OrgChartCorporateFileId = vr.OrgChartCorporateFileId; if (vr.OrgChartFactoryTechSupportFileId != null) dbVr.OrgChartFactoryTechSupportFileId = vr.OrgChartFactoryTechSupportFileId; if (vr.OrgChartLocalTechSupportFileId != null) dbVr.OrgChartLocalTechSupportFileId = vr.OrgChartLocalTechSupportFileId; if (vr.TechnicalItems != null) { dbVr.TechnicalItems.Clear(); dbVr.TechnicalItems.AddRange(vr.TechnicalItems); } if (vr.Applications != null) { dbVr.Applications.Clear(); dbVr.Applications.AddRange(vr.Applications); } if (vr.CommunicationFacilities != null) dbVr.CommunicationFacilities = vr.CommunicationFacilities; if (vr.PlanningProcess != null) dbVr.PlanningProcess = vr.PlanningProcess; if (vr.PlanningMonitoring != null) dbVr.PlanningMonitoring = vr.PlanningMonitoring; if (vr.ProductionPlanning != null) dbVr.ProductionPlanning = vr.ProductionPlanning; if (vr.QualityControlPlanning != null) dbVr.QualityControlPlanning = vr.QualityControlPlanning; if (vr.DesignProcess != null) dbVr.DesignProcess = vr.DesignProcess; if (vr.DesignChangeControl != null) dbVr.DesignChangeControl = vr.DesignChangeControl; if (vr.SoftwareList != null) { dbVr.SoftwareList.Clear(); dbVr.SoftwareList.AddRange(vr.SoftwareList); } if (vr.SupplierApprovalProcess != null) dbVr.SupplierApprovalProcess = vr.SupplierApprovalProcess; if (vr.TransmissionToSuppliers != null) dbVr.TransmissionToSuppliers = vr.TransmissionToSuppliers; if (vr.SupplierReevaluation != null) dbVr.SupplierReevaluation = vr.SupplierReevaluation; if (vr.SupplierQCMeans != null) dbVr.SupplierQCMeans = vr.SupplierQCMeans; if (vr.SupplierListFileId != null) dbVr.SupplierListFileId = vr.SupplierListFileId; if (vr.ProductionProcessControl != null) dbVr.ProductionProcessControl = vr.ProductionProcessControl; if (vr.ProductionSupportFileId != null) dbVr.ProductionSupportFileId = vr.ProductionSupportFileId; if (vr.ProductionAuthority != null) dbVr.ProductionAuthority = vr.ProductionAuthority; if (vr.IdentificationTraceability != null) dbVr.IdentificationTraceability = vr.IdentificationTraceability; if (vr.MaintenanceOfEquipment != null) dbVr.MaintenanceOfEquipment = vr.MaintenanceOfEquipment; if (vr.ProductionQualifiedStaff != null) { dbVr.ProductionQualifiedStaff.Clear(); dbVr.ProductionQualifiedStaff.AddRange(vr.ProductionQualifiedStaff); } if (vr.QualityDocuments != null) { dbVr.QualityDocuments.Clear(); dbVr.QualityDocuments.AddRange(vr.QualityDocuments); } if (vr.StandardManagement != null) dbVr.StandardManagement = vr.StandardManagement; if (vr.InternationalStandards != null) { dbVr.InternationalStandards.Clear(); dbVr.InternationalStandards.AddRange(vr.InternationalStandards); } if (vr.QualityAuthority != null) dbVr.QualityAuthority = vr.QualityAuthority; if (vr.QualityQualifiedStaff != null) { dbVr.QualityQualifiedStaff.Clear(); dbVr.QualityQualifiedStaff.AddRange(vr.QualityQualifiedStaff); } if (vr.QualityTraceability != null) dbVr.QualityTraceability = vr.QualityTraceability; if (vr.QcMethods != null) dbVr.QcMethods = vr.QcMethods; if (vr.QcPlans != null) dbVr.QcPlans = vr.QcPlans; if (vr.QcPlanFileId != null) dbVr.QcPlanFileId = vr.QcPlanFileId; if (vr.QcProcedures != null) dbVr.QcProcedures = vr.QcProcedures; if (vr.QcProceduresFileId != null) dbVr.QcProceduresFileId = vr.QcProceduresFileId; if (vr.ReceiptMaterials != null) dbVr.ReceiptMaterials = vr.ReceiptMaterials; if (vr.InventoryManagement != null) dbVr.InventoryManagement = vr.InventoryManagement; if (vr.NonConformityControl != null) dbVr.NonConformityControl = vr.NonConformityControl; if (vr.FailureStats != null) dbVr.FailureStats = vr.FailureStats; if (vr.PackagingTransport != null) dbVr.PackagingTransport = vr.PackagingTransport; if (vr.WasteManagement != null) dbVr.WasteManagement = vr.WasteManagement; } // ====== STEP 3 ====== if (dto.FinancialStanding != null) { if (requestFromDb.FinancialStanding == null) requestFromDb.FinancialStanding = new FinancialStanding(); var fs = dto.FinancialStanding; var dbFs = requestFromDb.FinancialStanding; if (fs.StepThreeApproverComment != null) dbFs.StepThreeApproverComment = fs.StepThreeApproverComment; if (fs.VendorFullName != null) dbFs.VendorFullName = fs.VendorFullName; if (fs.AuditReportsIds != null) { dbFs.AuditReportsIds.Clear(); dbFs.AuditReportsIds.AddRange(fs.AuditReportsIds); } if (fs.AuditorName != null) dbFs.AuditorName = fs.AuditorName; if (fs.AuditorAddress != null) dbFs.AuditorAddress = fs.AuditorAddress; if (fs.EBITDA_2024 != null) dbFs.EBITDA_2024 = fs.EBITDA_2024; if (fs.EBITDA_2022 != null) dbFs.EBITDA_2022 = fs.EBITDA_2022; if (fs.EBITDA_2023 != null) dbFs.EBITDA_2023 = fs.EBITDA_2023; if (fs.NetProfitMargin_2024 != null) dbFs.NetProfitMargin_2024 = fs.NetProfitMargin_2024; if (fs.NetProfitMargin_2022 != null) dbFs.NetProfitMargin_2022 = fs.NetProfitMargin_2022; if (fs.NetProfitMargin_2023 != null) dbFs.NetProfitMargin_2023 = fs.NetProfitMargin_2023; if (fs.CurrentRatio_2024 != null) dbFs.CurrentRatio_2024 = fs.CurrentRatio_2024; if (fs.CurrentRatio_2022 != null) dbFs.CurrentRatio_2022 = fs.CurrentRatio_2022; if (fs.CurrentRatio_2023 != null) dbFs.CurrentRatio_2023 = fs.CurrentRatio_2023; if (fs.CashFlowRatio_2024 != null) dbFs.CashFlowRatio_2024 = fs.CashFlowRatio_2024; if (fs.CashFlowRatio_2022 != null) dbFs.CashFlowRatio_2022 = fs.CashFlowRatio_2022; if (fs.CashFlowRatio_2023 != null) dbFs.CashFlowRatio_2023 = fs.CashFlowRatio_2023; if (fs.DebtEquityRatio_2024 != null) dbFs.DebtEquityRatio_2024 = fs.DebtEquityRatio_2024; if (fs.DebtEquityRatio_2022 != null) dbFs.DebtEquityRatio_2022 = fs.DebtEquityRatio_2022; if (fs.DebtEquityRatio_2023 != null) dbFs.DebtEquityRatio_2023 = fs.DebtEquityRatio_2023; if (fs.Bankers != null) { dbFs.Bankers.Clear(); dbFs.Bankers.AddRange(fs.Bankers); } } // ====== STEP 4 ====== if (dto.ExperienceAndAfterSales != null) { if (requestFromDb.ExperienceAndAfterSales == null) requestFromDb.ExperienceAndAfterSales = new ExperienceAndAfterSales(); var eas = dto.ExperienceAndAfterSales; var dbEas = requestFromDb.ExperienceAndAfterSales; if (eas.StepFourApproverComment != null) dbEas.StepFourApproverComment = eas.StepFourApproverComment; if (eas.ClientReferences != null) { dbEas.ClientReferences.Clear(); dbEas.ClientReferences.AddRange(eas.ClientReferences); } if (eas.ManufacturerProductInfo != null) dbEas.ManufacturerProductInfo = eas.ManufacturerProductInfo; if (eas.ClientRefDate != null) dbEas.ClientRefDate = eas.ClientRefDate; dbEas.AfterSalesReport = eas.AfterSalesReport; if (eas.WarrantyCertificateFile != null) dbEas.WarrantyCertificateFileId = eas.WarrantyCertificateFile.Id; dbEas.IssueTrackingSystem = eas.IssueTrackingSystem; } // ====== STEP 5 ====== if (dto.QualityHSERisk != null) { if (requestFromDb.QualityHSERisk == null) requestFromDb.QualityHSERisk = new QualityHSERisk(); var qhr = dto.QualityHSERisk; var dbQhr = requestFromDb.QualityHSERisk; if (qhr.StepFiveApproverComment != null) dbQhr.StepFiveApproverComment = qhr.StepFiveApproverComment; if (qhr.Certificates != null) { dbQhr.Certificates.Clear(); dbQhr.Certificates.AddRange(qhr.Certificates); } dbQhr.HasQualitySystem = qhr.HasQualitySystem; dbQhr.HasQaManual = qhr.HasQaManual; dbQhr.HasQaProcedures = qhr.HasQaProcedures; dbQhr.QaSystemMeetsStandard = qhr.QaSystemMeetsStandard; if (qhr.QaSystemDetails != null) dbQhr.QaSystemDetails = qhr.QaSystemDetails; dbQhr.QaSystemApprovedByAgency = qhr.QaSystemApprovedByAgency; if (qhr.ApprovedAgencyNames != null) dbQhr.ApprovedAgencyNames = qhr.ApprovedAgencyNames; dbQhr.HasAuditSchedule = qhr.HasAuditSchedule; dbQhr.HasHSEManual = qhr.HasHSEManual; dbQhr.HseMeetsStandard = qhr.HseMeetsStandard; if (qhr.EngineeringStandards != null) dbQhr.EngineeringStandards = qhr.EngineeringStandards; if (qhr.RiskManagement != null) dbQhr.RiskManagement = qhr.RiskManagement; dbQhr.HasTrainingFacility = qhr.HasTrainingFacility; if (qhr.TrainingDescription != null) dbQhr.TrainingDescription = qhr.TrainingDescription; if (qhr.QaSummary != null) { dbQhr.QaSummary.Clear(); dbQhr.QaSummary.AddRange(qhr.QaSummary); } if (qhr.CertInProcessDetails != null) dbQhr.CertInProcessDetails = qhr.CertInProcessDetails; if (qhr.CertProcessLetterId != null) dbQhr.CertProcessLetterId = qhr.CertProcessLetterId; } // ====== STEP 6 ====== if (dto.TypeTest != null) { if (requestFromDb.TypeTest == null) requestFromDb.TypeTest = new TypeTest(); var tt = dto.TypeTest; var dbTt = requestFromDb.TypeTest; if (tt.StepSixApproverComment != null) dbTt.StepSixApproverComment = tt.StepSixApproverComment; if (tt.TestType != null) dbTt.TestType = tt.TestType; dbTt.ThirdPartyReports = tt.ThirdPartyReports; dbTt.ThirdPartyCertificates = tt.ThirdPartyCertificates; if (tt.ThirdPartyReportsFileId != null) dbTt.ThirdPartyReportsFileId = tt.ThirdPartyReportsFileId; if (tt.ThirdPartyCertificatesFileId != null) dbTt.ThirdPartyCertificatesFileId = tt.ThirdPartyCertificatesFileId; dbTt.FactoryOwnLab = tt.FactoryOwnLab; dbTt.Lab17025Accredited = tt.Lab17025Accredited; dbTt.FactoryTestApprovedProcedure = tt.FactoryTestApprovedProcedure; if (tt.FactoryOwnLabFileId != null) dbTt.FactoryOwnLabFileId = tt.FactoryOwnLabFileId; if (tt.Lab17025AccreditedFileId != null) dbTt.Lab17025AccreditedFileId = tt.Lab17025AccreditedFileId; if (tt.FactoryTestApprovedProcedureFileId != null) dbTt.FactoryTestApprovedProcedureFileId = tt.FactoryTestApprovedProcedureFileId; } // ====== STEP 7 ====== if (dto.EquipmentGeneralArrangement != null) { if (requestFromDb.EquipmentGeneralArrangement == null) requestFromDb.EquipmentGeneralArrangement = new EquipmentGeneralArrangement(); var ega = dto.EquipmentGeneralArrangement; var dbEga = requestFromDb.EquipmentGeneralArrangement; if (ega.StepSevenApproverComment != null) dbEga.StepSevenApproverComment = ega.StepSevenApproverComment; dbEga.GaDrawingEnclosed = ega.GaDrawingEnclosed; dbEga.TypicalConnectionDrawing = ega.TypicalConnectionDrawing; dbEga.Product3DModel = ega.Product3DModel; if (ega.GaFileId != null) dbEga.GaFileId = ega.GaFileId; if (ega.ConnectionDrawingFileId != null) dbEga.ConnectionDrawingFileId = ega.ConnectionDrawingFileId; if (ega.Product3DModelFileId != null) dbEga.Product3DModelFileId = ega.Product3DModelFileId; } // ====== STEP 8 ====== if (dto.Compliance != null) { if (requestFromDb.Compliance == null) requestFromDb.Compliance = new Compliance(); var c = dto.Compliance; var dbC = requestFromDb.Compliance; if (c.StepEightApproverComment != null) dbC.StepEightApproverComment = c.StepEightApproverComment; dbC.GtpSubmitted = c.GtpSubmitted; if (c.GtpSubmittedFileId != null) dbC.GtpSubmittedFileId = c.GtpSubmittedFileId; dbC.ComplianceConfirmed = c.ComplianceConfirmed; if (c.ComplianceConfirmedFileId != null) dbC.ComplianceConfirmedFileId = c.ComplianceConfirmedFileId; if (c.GtpFileId != null) dbC.GtpFileId = c.GtpFileId; } // ====== STEP 9 ====== if (dto.Declaration != null) { if (requestFromDb.Declaration == null) requestFromDb.Declaration = new Declaration(); var d = dto.Declaration; var dbD = requestFromDb.Declaration; if (d.StepNineApproverComment != null) dbD.StepNineApproverComment = d.StepNineApproverComment; if (d.FullName != null) dbD.FullName = d.FullName; if (d.Designation != null) dbD.Designation = d.Designation; if (d.OnBehalfOf != null) dbD.OnBehalfOf = d.OnBehalfOf; if (d.SignedDate != null) dbD.SignedDate = d.SignedDate; if (d.PowerOfAttorneyFileId != null) dbD.PowerOfAttorneyFileId = d.PowerOfAttorneyFileId; } requestFromDb.Status = dto.Status ?? RequestStatus.CONFIRMED; requestFromDb.AdminObservations.Clear(); await _context.SaveChangesAsync(); return requestFromDb; } public async Task UpdateRequesCommentstAsync(long requestId, UpdatePqCommentsRequest dto) { // 1. Fetch the request including owned entities var pqRequest = await _context.PrequalificationRequests .FirstOrDefaultAsync(r => r.Id == requestId); if (pqRequest == null) return null; // 2. Map comments step-by-step // Step 1 if (dto.StepOneApproverComment != null) { pqRequest.GeneralInformation ??= new GeneralInformation(); pqRequest.GeneralInformation.StepOneApproverComment = dto.StepOneApproverComment; } // Step 2 if (dto.StepTwoApproverComment != null) { pqRequest.VendorResources ??= new VendorResources(); pqRequest.VendorResources.StepTwoApproverComment = dto.StepTwoApproverComment; } // Step 3 if (dto.StepThreeApproverComment != null) { pqRequest.FinancialStanding ??= new FinancialStanding(); pqRequest.FinancialStanding.StepThreeApproverComment = dto.StepThreeApproverComment; } // Step 4 if (dto.StepFourApproverComment != null) { pqRequest.ExperienceAndAfterSales ??= new ExperienceAndAfterSales(); pqRequest.ExperienceAndAfterSales.StepFourApproverComment = dto.StepFourApproverComment; } // Step 5 if (dto.StepFiveApproverComment != null) { pqRequest.QualityHSERisk ??= new QualityHSERisk(); pqRequest.QualityHSERisk.StepFiveApproverComment = dto.StepFiveApproverComment; } // Step 6 if (dto.StepSixApproverComment != null) { pqRequest.TypeTest ??= new TypeTest(); pqRequest.TypeTest.StepSixApproverComment = dto.StepSixApproverComment; } // Step 7 if (dto.StepSevenApproverComment != null) { pqRequest.EquipmentGeneralArrangement ??= new EquipmentGeneralArrangement(); pqRequest.EquipmentGeneralArrangement.StepSevenApproverComment = dto.StepSevenApproverComment; } // Step 8 if (dto.StepEightApproverComment != null) { pqRequest.Compliance ??= new Compliance(); pqRequest.Compliance.StepEightApproverComment = dto.StepEightApproverComment; } // Step 9 if (dto.StepNineApproverComment != null) { pqRequest.Declaration ??= new Declaration(); pqRequest.Declaration.StepNineApproverComment = dto.StepNineApproverComment; } // 3. Save changes _context.PrequalificationRequests.Update(pqRequest); await _context.SaveChangesAsync(); return pqRequest; } /* public async Task GetRequestByIdAsync(long requestId) { return await _context.PrequalificationRequests.AsNoTracking() .FirstOrDefaultAsync(r => r.Id == requestId); } */ public async Task GetRequestByIdAsync(long requestId) { return await _context.PrequalificationRequests .AsNoTracking() .Include(r => r.VisitRequest) // <--- Essential for your issue .Include(r => r.AssignedTo) .Include(r => r.Inspectors) .Include(r => r.Vendor) .Include(r => r.GeneralInformation) // Include other steps if you need them in the details view .FirstOrDefaultAsync(r => r.Id == requestId); } public async Task> GetRequestsForVendorPaginatedAsync( long vendorId, int page, int size) { // 1. Validation to prevent EF Core errors if (page < 0) page = 0; if (size <= 0) size = 10; var query = _context.PrequalificationRequests .Include(r => r.VisitRequest) .Where(r => r.VendorId == vendorId); var totalCount = await query.CountAsync(); // 2. Add Try-Catch to see the error in your debugger/logs try { var items = await query.OrderByDescending(r => r.SubmissionDate) .Skip(page * size) .Take(size) .ToListAsync(); return new PagedResult(items, totalCount, page, size); } catch (Exception ex) { // Log the exception here throw new Exception($"Error fetching paginated requests: {ex.Message}"); } } public async Task> GetAllRequestsPaginatedAsync( int page, int size, RequestStatus? status, long? userId, long? employeeId) { //var query = _context.PrequalificationRequests.AsQueryable(); var query = _context.PrequalificationRequests .Include(r => r.AssignedTo) .Include(r => r.Inspectors) .Include(r => r.VisitRequest) .Include(r => r.AssessmentReport) .AsQueryable(); if (status.HasValue) { query = query.Where(r => r.Status == status.Value); } if (userId.HasValue) { query = query.Where(r => r.Vendor.UserId == userId.Value); } if (employeeId.HasValue) { var employeeIdValue = employeeId.Value; // Filter where the employee is either the AssignedTo person OR one of the Inspectors. // EF Core will automatically handle joins and distinct results for PrequalificationRequest entities. query = query.Where(r => // Condition 1: AssignedTo User ID matches r.AssignedToUserId == employeeIdValue || // Use the FK for potentially simpler query // Condition 2: Is one of the Inspectors (check the collection) r.Inspectors.Any(i => i.Id == employeeIdValue) ); } var totalCount = await query.CountAsync(); var items = await query.OrderByDescending(r => r.Timestamp) .Skip(page * size) .Take(size) .ToListAsync(); return new PagedResult(items, totalCount, page, size); } public async Task> GetAllRequestsListAsync( RequestStatus? status, long? userId, long? employeeId) { var query = _context.PrequalificationRequests.AsQueryable(); // --- Same Filtering Logic --- if (status.HasValue) { query = query.Where(r => r.Status == status.Value); } if (userId.HasValue) { query = query.Where(r => r.Vendor.UserId == userId.Value); } if (employeeId.HasValue) { var employeeIdValue = employeeId.Value; query = query.Where(r => r.AssignedToUserId == employeeIdValue || r.Inspectors.Any(i => i.Id == employeeIdValue) ); } // --- No Paging logic, just order and list --- return await query.OrderByDescending(r => r.Timestamp) .ToListAsync(); } public async Task UpdateAdminObservationsAsync(long requestId, List observationDtos) { var request = await _context.PrequalificationRequests .Include(r => r.AdminObservations) .FirstOrDefaultAsync(r => r.Id == requestId); if (request == null) { return null; } request.AdminObservations.Clear(); if (observationDtos != null) { foreach (var dto in observationDtos) { request.AdminObservations.Add(new AdminObservation { StepNumber = dto.StepNumber, EnableUpdate = dto.EnableUpdate, Description = dto.Description }); } } request.Status = RequestStatus.MISSING_INFO; await _context.SaveChangesAsync(); return request; } public async Task AssignPqRequestToEmployeeAsync(long requestId, long? employeeId, DateTime? deadline, long currentUserId) { var requestFromDb = await _context.PrequalificationRequests .Include(r => r.Vendor) .ThenInclude(v => v.User) .FirstOrDefaultAsync(r => r.Id == requestId); if (requestFromDb == null) return null; var defaultEmployee = new User { Name = "Unknown Employee" }; User employee = defaultEmployee; if (employeeId.HasValue) { var foundEmployee = await _context.Users .Where(u => u.Id == employeeId.Value) .FirstOrDefaultAsync(); if (foundEmployee == null) { throw new KeyNotFoundException($"Employee with ID {employeeId.Value} not found."); } employee = foundEmployee; employee.RequestsEvaluationIds.Add(requestFromDb.Id); } requestFromDb.AssignedToUserId = employeeId; //requestFromDb.Timestamp = DateTime.UtcNow; requestFromDb.Status = RequestStatus.UNDER_REVIEW; requestFromDb.AssignmentDate = DateTime.UtcNow; if (deadline != null) { requestFromDb.deadline = deadline; } _context.PrequalificationRequests.Update(requestFromDb); await SendAssignmentNotifications(requestFromDb, currentUserId, employee); await _context.SaveChangesAsync(); await _context.Entry(requestFromDb).Reference(r => r.AssignedTo).LoadAsync(); return requestFromDb; } private async Task SendAssignmentNotifications(PrequalificationRequest assignedRequest, long currentUserId, User assignedEmployee) { try { // Get all admin user IDs var adminUserIds = await _userService.GetAdminUserIdsAsync(); // Prepare list of users to notify var usersToNotify = new List(); // Add all admins if (adminUserIds.Any()) { usersToNotify.AddRange(adminUserIds); } // Add the assigned employee (if exists) if (assignedRequest.AssignedToUserId.HasValue) { usersToNotify.Add(assignedRequest.AssignedToUserId.Value); } // Add the current user (the one who performed the assignment) usersToNotify.Add(currentUserId); // Remove duplicates usersToNotify = usersToNotify.Distinct().ToList(); if (usersToNotify.Any()) { var vendorName = assignedRequest.Vendor?.User?.Name ?? "Unknown Vendor"; var employeeName = assignedEmployee?.Name ?? "Unknown Employee"; // Use the employee object we passed var notification = new NotificationModel { SenderId = currentUserId, Subject = "PQ-Request Assignment", Content = $"PQ-request number: {assignedRequest.Id} assigned to {employeeName}", Action = Action.Pq_REQUEST_ASSIGNED, ActionId = assignedRequest.Id, LogUrl = "/images/pq-assignment.png", Status = states.WAITING }; await _notificationService.SendNotificationToListOfUsers(usersToNotify, notification); _logger.LogInformation($"Sent PQ request assignment notification to {usersToNotify.Count} users"); } } catch (Exception ex) { _logger.LogError(ex, "Failed to send assignment notification for PQ request {RequestId}", assignedRequest.Id); } } public async Task GetRequestByIdWithInspectorsAsync(long requestId) { return await _context.PrequalificationRequests .Include(r => r.Inspectors) .AsNoTracking() .FirstOrDefaultAsync(r => r.Id == requestId); } public async Task<(PrequalificationRequest? Request, HttpStatusCode StatusCode, string Message)> AssignToInspectors( long requestId, AssignInspectorsRequest request) { var pqRequest = await _context.PrequalificationRequests .Include(r => r.Inspectors) .FirstOrDefaultAsync(r => r.Id == requestId); if (pqRequest == null) { return (null, HttpStatusCode.NotFound, $"Prequalification Request with ID {requestId} not found."); } var newInspectors = new List(); foreach (var userId in request.InspectorsIds.Distinct()) { var inspector = await _userService.FindByIdAsync(userId); if (inspector == null) { return (null, HttpStatusCode.NotAcceptable, $"No user found with ID {userId}. Aborting assignment."); } newInspectors.Add(inspector); inspector.InspectionPqId = requestId; } pqRequest.Inspectors.Clear(); foreach (var inspector in newInspectors) { _context.Users.Attach(inspector); pqRequest.Inspectors.Add(inspector); } pqRequest.Status = RequestStatus.FACTORY_VISIT; await _context.SaveChangesAsync(); var updatedRequest = await GetRequestByIdWithInspectorsAsync(requestId); return (updatedRequest, HttpStatusCode.OK, "Inspectors assigned successfully."); } /* public async Task UpdateRequestStatusAsync(long requestId, UpdateRequestStatus request, User currentUser) { var requestFromDb = await _context.PrequalificationRequests .FirstOrDefaultAsync(r => r.Id == requestId); if (requestFromDb == null) return null; var oldStatus = requestFromDb.Status; requestFromDb.Status = request.Status; if (request.Reason != null) { requestFromDb.Reason = request.Reason; } _context.PrequalificationRequests.Update(requestFromDb); if (request.Status == RequestStatus.CERTIFIED && oldStatus != RequestStatus.CERTIFIED) { try { await _productService.GenerateProductFromPqService(requestFromDb); await _certificationService.GenerateCertificate(requestFromDb, currentUser); } catch (Exception ex) { Console.WriteLine($"Unexpected error creating product for PQ Request {requestId}: {ex.Message}"); } } await _context.SaveChangesAsync(); return requestFromDb; } */ // 📁 Services/PrequalificationRequestService.cs public async Task UpdateRequestStatusAsync(long requestId, UpdateRequestStatus request, User currentUser) { var requestFromDb = await _context.PrequalificationRequests .Include(r => r.GeneralInformation) .Include(r => r.Vendor) .ThenInclude(v => v.User) .FirstOrDefaultAsync(r => r.Id == requestId); if (requestFromDb == null) return null; var oldStatus = requestFromDb.Status; requestFromDb.Status = request.Status; if (request.Reason != null) { requestFromDb.Reason = request.Reason; } if (request.Status == RequestStatus.CERTIFIED) { requestFromDb.ApprovalDate = new DateTime(); } _context.PrequalificationRequests.Update(requestFromDb); if (requestFromDb.Status == RequestStatus.CERTIFIED && oldStatus != RequestStatus.CERTIFIED) { try { await _productService.GenerateProductFromPqService(requestFromDb); await _certificationService.GenerateCertificate(requestFromDb, currentUser); } catch (Exception ex) { Console.WriteLine($"Product/Certification Creation Failed for PQ {requestId}. Details: {ex.Message}"); } } await _context.SaveChangesAsync(); return requestFromDb; } public async Task SendManualReminderAsync(long pqRequestId, string? comment) { // Fetch the request with necessary relations var request = await _context.PrequalificationRequests .Include(r => r.Vendor) .ThenInclude(v => v.User) .FirstOrDefaultAsync(r => r.Id == pqRequestId); // Validate request and existence of vendor email if (request == null || request.Vendor?.User?.Email == null) { return false; } // Call the email service await _emailService.SendManualPqReminderAsync( request.Vendor.User.Email, request, comment ); return true; } } }