using Neo.Afx.Common; using Neo.Afx.Services.Integration; using Neo.Afx.ViewModels; using Neo.LegitimateLicences.ApplicationRequest.Models.Database; using Neo.LegitimateLicences.Common; using Neo.LegitimateLicences.Data.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using Neo.LegitimateLicences.Logic.ApplicationLogic; using Neo.LegitimateLicences.Logic.Helpers; using Neo.Afx.Mvc; namespace Neo.LegitimateLicences.ApplicationRequest { public class ApplicantDetails { public string Name { get;set; } public string Cell { get;set; } public long? ProvinceID { get;set; } public long? RegionID { get;set; } public long? VerifiedMemberID { get;set; } public long? AssociationID { get; set; } } public partial class ApplicationRequestController { #region New /// /// Load New console /// /// public ActionResult New() { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) return RedirectToAction("Default", "Dashboard"); var m = new NewApplicationRequestModel { Lookups = GetLookupsForNewApplicationView() }; #region Get User's Office Location UserProfileHelper userProfileHelper = new UserProfileHelper(Profile.UserID, Profile.OfficeLocationID); var officeLocation = userProfileHelper.OfficeLocation; m.IsNPTR = userProfileHelper.IsNPTR; m.IsTAT = userProfileHelper.IsTAT; m.IsNewApplicationsRestrictedToList = (officeLocation.DivisionTypeID == (short)DivisionTypeEnum.PRE); // Feature flag for e-hailing providers (used in view for top-level dropdowns) try { var db = new LegitimateDatabase(); var flagVal = db.Context.Database.SqlQuery( "SELECT SettingValue FROM [System].[Settings] WHERE SettingName = @p0", new object[] { "ehailing.providers.enabled" } ).FirstOrDefault(); ViewBag.EhailingProvidersEnabled = string.Equals(flagVal, "TRUE", StringComparison.OrdinalIgnoreCase) || string.Equals(flagVal, "1"); } catch { ViewBag.EhailingProvidersEnabled = false; } #endregion #region Get Vehicle/Service Types ApplicationLogic applicationLogic = new ApplicationLogic(); m.VehicleServiceTypeCollection = applicationLogic.VehicleServiceTypeCollectionGet(); #endregion if (m.IsTAT) { return View("New.TAT", m); } return View("New", m); } #endregion #region PlatformProviderSearchRow /// /// Lightweight projection for searching platform providers from /// Verified.Vw_ProviderRegistry. Kept private to this controller as it /// is only used for JSON responses in the conversion flow. /// private class PlatformProviderSearchRow { public long PlatformProviderID { get; set; } public string LegalName { get; set; } public string TradingName { get; set; } public string CertificateNumber { get; set; } public string Status { get; set; } } #endregion #region GetLookupsForNewApplicationView /// /// Retrieve list of master datasources for ApplicationRequest\New view /// /// List public List GetLookupsForNewApplicationView() { var lookups = new List(); var integrationStore = new SqlIntegrationStore(); try { UserProfileHelper userProfileHelper = new UserProfileHelper(Profile.UserID, Profile.OfficeLocationID); var officeLocation = userProfileHelper.OfficeLocation; integrationStore.Open(); lookups.Add(new LookupList("IDTypes", integrationStore.GetDataEntities("IDTypes", string.Empty).Where(o => o.Key != ((short)IdTypeEnum.TaxiAssociationRegistrationNumber).ToString()).ToList().OrderBy(a => a.Title))); lookups.Add(new LookupList("ApplicationRequestTypes", integrationStore.GetDataEntities("ApplicationRequestTypes", string.Empty).OrderBy(a => a.Title))); lookups.Add(new LookupList("VehicleTypes", integrationStore.GetDataEntities("VehicleTypes", string.Empty).OrderBy(a => a.Title))); lookups.Add(new LookupList("ServiceTypes", integrationStore.GetDataEntities("ServiceTypesDivision", string.Empty).Where(x => x.Properties["divisiontypeid"] == officeLocation.DivisionTypeID.ToString() && x.Properties["provinceid"] == officeLocation.ProvinceID.ToString()).OrderBy(a => a.Title))); lookups.Add(new LookupList("Regions", integrationStore.GetDataEntities("Regions", string.Empty).OrderBy(a => a.Title))); lookups.Add(new LookupList("Provinces", integrationStore.GetDataEntities("Provinces", string.Empty).OrderBy(a => a.Title))); } finally { integrationStore.Close(); } return lookups; } #endregion #region ApplicantSearch /// /// Search applicant by ID number to determine valid application types/licences /// /// /// Optional; omitted by some callers (e.g. LicenceIssueRequest). Defaults to 0. /// JsonNetResult [HttpPost] public JsonNetResult ApplicantSearch(string idOrBusinessRegistrationNumber, short? applicationRequestTypeID) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } // When not posted (null) or client sends undefined, treat as 0 — only affects accreditation-without-OL vehicle-type branch below. short requestTypeId = applicationRequestTypeID.GetValueOrDefault(); var database = new LegitimateDatabase(); var applicationDatabase = new ApplicationDatabase(); #region Get User's Office Location UserProfileHelper userProfileHelper = new UserProfileHelper(Profile.UserID, Profile.OfficeLocationID); var officeLocation = userProfileHelper.OfficeLocation; #endregion var existingAccreditation = new List(); var allowedVehicleTypes = (short)VehicleTypeEnum.Bus + "," + (short)VehicleTypeEnum.Midibus + "," + (short)VehicleTypeEnum.Minibus + "," + (short)VehicleTypeEnum.MotorCar + "," + (short)VehicleTypeEnum.Motorcycle; if (requestTypeId == (short)ApplicationRequestTypeEnum.ApplicationForAccreditationWithoutOperatingLicence) allowedVehicleTypes = ((short)VehicleTypeEnum.Other).ToString(); var existingLicences = new List(); var appsInProgress = new List(); var allowedNewApplications = new List(); // Null when no verified member for this ID (do not use new() — branches below must null-check) Pr_MemberGet_Result verifiedMember = null; var applicant = new ApplicantDetails(); var memberState = ""; #region Default allowed application types that applies to everyone var allowedTypes = new List { Convert.ToString((short)ApplicationRequestTypeEnum.NewOperatingLicence), Convert.ToString((short)ApplicationRequestTypeEnum.ApplicationForAccreditation), Convert.ToString((short)ApplicationRequestTypeEnum.ApplicationForAccreditationWithoutOperatingLicence), Convert.ToString((short)ApplicationRequestTypeEnum.DeceasedTransfer), Convert.ToString((short)ApplicationRequestTypeEnum.NormalTransfer) }; // NPTR-specific: allow E-hailing App Provider Registration types only when feature flag enabled // Feature flag: ehailing.providers.enabled bool providersEnabled = false; try { var dbFlag = new LegitimateDatabase(); var flagVal = dbFlag.Context.Database.SqlQuery( "SELECT SettingValue FROM [System].[Settings] WHERE SettingName = @p0", new object[] { "ehailing.providers.enabled" } ).FirstOrDefault(); providersEnabled = string.Equals(flagVal, "TRUE", StringComparison.OrdinalIgnoreCase) || string.Equals(flagVal, "1"); } catch { providersEnabled = false; } if (officeLocation.DivisionTypeID == (short)DivisionTypeEnum.NPTR && providersEnabled) { var ehailingProviderTypes = new [] { Convert.ToString((short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration), Convert.ToString((short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal), Convert.ToString((short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions) }; foreach (var t in ehailingProviderTypes) { if (!allowedTypes.Contains(t)) allowedTypes.Add(t); } } else { // Safety: ensure e-hailing provider types are NOT present when flag is off allowedTypes.Remove(Convert.ToString((short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration)); allowedTypes.Remove(Convert.ToString((short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal)); allowedTypes.Remove(Convert.ToString((short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions)); } #endregion #region Load data verifiedMember = database.GetVerifiedMember(idOrBusinessRegistrationNumber, Profile.UserID); appsInProgress = applicationDatabase.GetApplicantApplicationsInProgress(idOrBusinessRegistrationNumber, Profile.UserID); existingLicences = applicationDatabase.GetApplicationCreateMemberLicences(idOrBusinessRegistrationNumber, Profile.UserID); var integrationStore = new SqlIntegrationStore(); integrationStore.Open(); var applicantAssociations = new LookupList("MemberAssociations", integrationStore.GetDataEntities("MemberAssociations", "IDNumberOrBusinessRegistrationNo=" + idOrBusinessRegistrationNumber + "&ProvinceID=" + userProfileHelper.OfficeLocation.ProvinceID)); integrationStore.Close(); if (verifiedMember != null) { existingAccreditation = applicationDatabase.GetApplicationCreateMemberAccreditations(verifiedMember.MemberID, Profile.UserID); } if (officeLocation.DivisionTypeID == (short)DivisionTypeEnum.PRE) { allowedNewApplications = applicationDatabase.GetApplicationCreateMemberAllowedNewSummary(idOrBusinessRegistrationNumber, Profile.UserID); } #endregion #region Add allowed types to list based on licences received foreach (var licence in existingLicences) { if (licence.AllowedApplicationRequestTypes != null) { foreach (var type in licence.AllowedApplicationRequestTypes.Split(',')) { if (!allowedTypes.Contains(type)) { allowedTypes.Add(type); } } } } if (existingAccreditation.Count > 0) { allowedTypes.Remove(Convert.ToString((short)ApplicationRequestTypeEnum.ApplicationForAccreditation)); allowedTypes.Remove(Convert.ToString((short)ApplicationRequestTypeEnum.ApplicationForAccreditationWithoutOperatingLicence)); foreach (var licence in existingAccreditation) { if (licence.AllowedApplicationRequestTypes == null) continue; foreach (var type in licence.AllowedApplicationRequestTypes.Split(',')) { if (!allowedTypes.Contains(type)) { allowedTypes.Add(type); } } } } // PRE + ehailing.providers.enabled: add type 63 (Convert Metered Taxi to E-hailing) when applicant has at least one conversion-eligible application if (officeLocation.DivisionTypeID == (short)DivisionTypeEnum.PRE && providersEnabled && applicationDatabase.HasConversionEligibleApplications(idOrBusinessRegistrationNumber, Profile.UserID)) { var type63 = Convert.ToString((short)ApplicationRequestTypeEnum.ConversionOfMeteredTaxiToEhailing); if (!allowedTypes.Contains(type63)) allowedTypes.Add(type63); } #endregion #region Populate applicant name etc. if (verifiedMember != null) { memberState = "ExistingVerifiedMember"; applicant.Name = verifiedMember.FullName; applicant.Cell = verifiedMember.TelCell; // Province and region come from the office the operator selected before starting the application applicant.ProvinceID = userProfileHelper.OfficeLocation.ProvinceID; applicant.RegionID = userProfileHelper.OfficeLocation.RegionID; applicant.VerifiedMemberID = verifiedMember.MemberID; applicant.AssociationID = verifiedMember.AssociationID; } else if (appsInProgress != null && appsInProgress.Count > 0) { memberState = "ExistingApplicant"; var appToUse = appsInProgress.First(); applicant.Name = appToUse.ApplicantName; applicant.Cell = appToUse.TelCell; applicant.RegionID = appToUse.RegionID; applicant.ProvinceID = userProfileHelper.OfficeLocation.ProvinceID; applicant.AssociationID = verifiedMember?.AssociationID; } else if (existingLicences != null && existingLicences.Count > 0) { memberState = "ExistingMemberInOtherSystems"; var licenceToUse = existingLicences.First(); applicant.Name = licenceToUse.OperatorName; applicant.Cell = licenceToUse.TelCell; // Province and region come from the office the operator selected before starting the application applicant.ProvinceID = userProfileHelper.OfficeLocation.ProvinceID; applicant.RegionID = userProfileHelper.OfficeLocation.RegionID; applicant.AssociationID = verifiedMember?.AssociationID; } else { memberState = "NewApplicant"; applicant.ProvinceID = userProfileHelper.OfficeLocation.ProvinceID; applicant.RegionID = userProfileHelper.OfficeLocation.RegionID; } #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = true, Result = new { MemberState = memberState, AllowedVehicleTypes = allowedVehicleTypes, AllowedTypes = string.Join(",", allowedTypes), Licences = existingLicences, Accreditations = existingAccreditation, Applications = appsInProgress, Applicant = applicant, AllowedNewApplications = allowedNewApplications, ApplicantAssociations = applicantAssociations.List } } }; } catch (Exception ex) { #region Error Handling #region Error Additional Data Dictionary additionalData = new Dictionary { { "idOrBusinessRegistrationNumber", idOrBusinessRegistrationNumber } }; #endregion string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "ApplicantSearch", additionalData); #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region GetConversionEligibleApplications /// /// Returns applications (one row per application+licence) eligible as source for Convert Metered Taxi to E-hailing (type 63). /// Used when type 63 is selected and user is on the RequestLicences step. /// [HttpPost] public JsonNetResult GetConversionEligibleApplications(string idOrBusinessRegistrationNumber) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var applicationDatabase = new ApplicationDatabase(); var list = applicationDatabase.GetConversionEligibleApplications(idOrBusinessRegistrationNumber ?? string.Empty, Profile.UserID); return new JsonNetResult() { Data = new JsonBaseResult() { Success = true, Result = new { items = list } } }; } catch (Exception ex) { var error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "GetConversionEligibleApplications", new Dictionary { { "idOrBusinessRegistrationNumber", idOrBusinessRegistrationNumber } }); return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region CreateApplicationPrecheck /// /// Create application precheck record and return precheck result outcome /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// [HttpPost] public JsonNetResult CreateApplicationPrecheck(short applicationRequestTypeID, short sourceApplicationID, string applicantName, string applicantCell, short idTypeID, string idOrBusinessRegistrationNumber, string originatingLicenceNumber, string originatingAccreditationNumber, short? vehicleTypeID, string serviceTypeIDs, short numberOfLicencesRequired, short? applicantProvinceID, short? applicantRegionID, long? applicationAssociationID, string applicationAllowedNewLicenceIDs, string selectedRouteIDs, long? parentApplicationDetailID = null, long? parentApplicationLicenceID = null) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var applicationDatabase = new ApplicationDatabase(); bool precheckPassed = true; long applicationPrecheckDetailID = 0; var precheckOutcomes = applicationDatabase.CreateApplicationPrecheck( applicationRequestTypeID, sourceApplicationID, applicantName, applicantCell, idTypeID, idOrBusinessRegistrationNumber, originatingLicenceNumber, originatingAccreditationNumber, vehicleTypeID, serviceTypeIDs, numberOfLicencesRequired, applicantProvinceID, applicantRegionID, applicationAssociationID, applicationAllowedNewLicenceIDs, selectedRouteIDs, parentApplicationDetailID, parentApplicationLicenceID, Profile.UserID); // NPTR E-hailing provider registrations (60/61/62) do not require an originating licence. // If the generic precheck flagged that as a failure, mark it as not applicable so the flow can proceed. if (applicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration || applicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal || applicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions) { if (precheckOutcomes != null) { foreach (var outcome in precheckOutcomes) { if (!outcome.IsSuccessful && !string.IsNullOrEmpty(outcome.Title) && outcome.Title.IndexOf("originating licence", StringComparison.OrdinalIgnoreCase) >= 0) { outcome.IsSuccessful = true; if (!string.IsNullOrEmpty(outcome.OutcomeDetails)) { outcome.OutcomeDetails = "Not applicable for provider registration"; } } } } } if (precheckOutcomes != null) { if (precheckOutcomes.Find(a => !a.IsSuccessful) != null) { precheckPassed = false; } var firstOutcome = precheckOutcomes.FirstOrDefault(); if (firstOutcome != null) { applicationPrecheckDetailID = firstOutcome.ApplicationPrecheckDetailID; } } return new JsonNetResult() { Data = new JsonBaseResult() { Success = true, Result = new { PrecheckOutcomes = precheckOutcomes, ApplicationPrecheckDetailID = applicationPrecheckDetailID, PrecheckPassed = precheckPassed } } }; } catch (Exception ex) { #region Error Handling #region Error Additional Data Dictionary additionalData = new Dictionary(); additionalData.Add("applicationRequestTypeID", applicationRequestTypeID); additionalData.Add("sourceApplicationID", sourceApplicationID); additionalData.Add("applicantName", applicantName); additionalData.Add("applicantCell", applicantCell); additionalData.Add("idTypeID", idTypeID); additionalData.Add("idOrBusinessRegistrationNumber", idOrBusinessRegistrationNumber); additionalData.Add("originatingLicenceNumber", originatingLicenceNumber); additionalData.Add("originatingAccreditationNumber", originatingAccreditationNumber); additionalData.Add("vehicleTypeID", vehicleTypeID); additionalData.Add("serviceTypeIDs", serviceTypeIDs); additionalData.Add("numberOfLicencesRequired", numberOfLicencesRequired); additionalData.Add("applicantProvinceID", applicantProvinceID); additionalData.Add("applicantRegionID", applicantRegionID); additionalData.Add("applicationAssociationID", applicationAssociationID); additionalData.Add("applicationAllowedNewLicenceIDs", applicationAllowedNewLicenceIDs); additionalData.Add("selectedRouteIDs", selectedRouteIDs); #endregion string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "CreateApplicationPrecheck", additionalData); #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region GetApplicationDocuments /// /// Retrieve the list of documents required/optional for an application based of precheck results /// /// /// /// /// JsonNetResult [HttpPost] public JsonNetResult GetApplicationDocuments(long applicationPrecheckDetailID, short applicationRequestTypeID, long? memberID) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var applicationDatabase = new ApplicationDatabase(); // Optional primary service type context for per-service-type document // rules. For the Conversion of Metered Taxi to E-hailing application // type (ID 63), we always treat the primary service type as EHailing // so that the EHailing-specific document rules seeded in // Md.ApplicationRequestTypeDocumentSetup are applied. short? primaryServiceTypeID = null; if (applicationRequestTypeID == 63 /*Conversion of Metered Taxi to E-hailing*/) { primaryServiceTypeID = (short)ServiceTypeEnum.EHailing; } var applicationDocuments = applicationDatabase.GetApplicationRequestTypeDocuments( applicationPrecheckDetailID, applicationRequestTypeID, (long)WorkflowTemplatesEnum.ApplicationRequestV1, memberID, Profile.UserID, primaryServiceTypeID); return new JsonNetResult() { Data = new JsonBaseResult() { Success = true, Result = new { ApplicationDocuments = applicationDocuments } } }; } catch (Exception ex) { #region Error Handling #region Error Additional Data Dictionary additionalData = new Dictionary(); additionalData.Add("applicationPrecheckDetailID", applicationPrecheckDetailID); additionalData.Add("applicationRequestTypeID", applicationRequestTypeID); additionalData.Add("memberID", memberID); #endregion string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "GetRequiredDocuments", additionalData); #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region EhailingProvidersEnabled [HttpGet] public JsonNetResult EhailingProvidersEnabled() { bool enabled = false; try { var db = new LegitimateDatabase(); var flagVal = db.Context.Database.SqlQuery( "SELECT SettingValue FROM [System].[Settings] WHERE SettingName = @p0", new object[] { "ehailing.providers.enabled" } ).FirstOrDefault(); enabled = string.Equals(flagVal, "TRUE", StringComparison.OrdinalIgnoreCase) || string.Equals(flagVal, "1"); } catch { enabled = false; } return new JsonNetResult { Data = new JsonBaseResult { Success = true, Result = new { enabled = enabled } } }; } #endregion #region CreateApplication /// /// Create Application /// /// /// [HttpPost] public JsonNetResult CreateApplication(long applicationPrecheckDetailID, long? sourceApplicationDetailID = null, long? sourceApplicationLicenceID = null, long? platformProviderID = null, bool? isContractedService = null) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var applicationDatabase = new ApplicationDatabase(); // Used for office lookup (non-conversion path) and NPTR provider-submitted notifications below. var db = new LegitimateDatabase(); Neo.LegitimateLicences.ApplicationRequest.Models.Database.Vw_ApplicationDetails_Light applicationDetails = new Neo.LegitimateLicences.ApplicationRequest.Models.Database.Vw_ApplicationDetails_Light(); // Type 63 (Convert Metered Taxi to E-hailing): when all three conversion params provided, create via conversion path if (sourceApplicationDetailID.HasValue && sourceApplicationDetailID.Value > 0 && sourceApplicationLicenceID.HasValue && sourceApplicationLicenceID.Value > 0 && platformProviderID.HasValue && platformProviderID.Value > 0) { applicationDetails = applicationDatabase.CreateConversionApplication( sourceApplicationDetailID.Value, sourceApplicationLicenceID.Value, platformProviderID.Value, Profile.UserID); } else { var office = db.GetOfficeLocation(Profile.OfficeLocationID.Value); if (office.DivisionTypeID == (short)DivisionTypeEnum.TAT) { applicationDetails = applicationDatabase.TAT_CreateApplication(applicationPrecheckDetailID, Profile.UserID); } else { applicationDetails = applicationDatabase.CreateApplication(applicationPrecheckDetailID, Profile.UserID, isContractedService); } } // Note: NPTR E‑hailing provider registration types (60/61/62) use existing payment console for POP upload and receipt capture. // Fire submitted notification (best effort) try { if (applicationDetails != null && (applicationDetails.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration || applicationDetails.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal || applicationDetails.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions)) { var templateId = db.Context.Database.SqlQuery( "SELECT TOP 1 MessageTemplateID FROM Crm.MessageTemplates WHERE MessageTemplateKey = @p0", new object[] { "APP_PROVIDER_SUBMITTED" } ).FirstOrDefault(); if (templateId > 0) { db.Context.Database.ExecuteSqlCommand( "EXEC Crm.Pr_MessageCreateTemplatedEmails @MessageTemplateID", new System.Data.SqlClient.SqlParameter("@MessageTemplateID", templateId) ); } } } catch { } return new JsonNetResult() { Data = new JsonBaseResult() { Success = true, Result = new { ApplicationDetails = applicationDetails } } }; } catch (Exception ex) { #region Error Handling #region Error Additional Data Dictionary additionalData = new Dictionary(); additionalData.Add("applicationPrecheckDetailID", applicationPrecheckDetailID); #endregion string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "CreateApplication", additionalData); #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region StartConversionApplication /// /// Start a dedicated conversion application (type 63) for a specific /// source application/licence and selected platform provider. /// [HttpPost] public JsonNetResult StartConversionApplication(long sourceApplicationDetailID, long sourceApplicationLicenceID, long platformProviderID) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var applicationDatabase = new ApplicationDatabase(); // The actual creation is done in the App.Pr_ConversionApplicationCreate // stored procedure – this call will return the new light-view row // when successful. var conversionApp = applicationDatabase.CreateConversionApplication( sourceApplicationDetailID, sourceApplicationLicenceID, platformProviderID, Profile.UserID); if (conversionApp == null) { throw new Exception("#EXPOSE_ERROR#Unable to create conversion application."); } return new JsonNetResult { Data = new JsonBaseResult { Success = true, Result = new { ApplicationDetailID = conversionApp.ApplicationDetailID, ReferenceNumber = conversionApp.ApplicationNumber } } }; } catch (Exception ex) { #region Error Handling var additionalData = new Dictionary { { "sourceApplicationDetailID", sourceApplicationDetailID }, { "sourceApplicationLicenceID", sourceApplicationLicenceID }, { "platformProviderID", platformProviderID } }; string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "StartConversionApplication", additionalData); #endregion return new JsonNetResult { Data = new JsonBaseResult { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region Conversion helpers /// /// Check whether a conversion application (type 63) already exists for /// the given source application/licence. This prevents users from /// starting duplicate conversion processes for the same licence. /// [HttpPost] public JsonNetResult GetConversionStatus(long sourceApplicationDetailID, long sourceApplicationLicenceID) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var applicationDatabase = new ApplicationDatabase(); var existing = applicationDatabase.GetExistingConversionApplication( sourceApplicationDetailID, sourceApplicationLicenceID); // Always return the same anonymous shape so that callers can // reliably inspect HasExisting and, when true, navigate to the // existing conversion application. var result = new { HasExisting = (existing != null), ApplicationDetailID = existing != null ? existing.ApplicationDetailID : 0L, ReferenceNumber = existing != null ? existing.ApplicationNumber : null }; return new JsonNetResult { Data = new JsonBaseResult { Success = true, Result = result } }; } catch (Exception ex) { var additionalData = new Dictionary { { "sourceApplicationDetailID", sourceApplicationDetailID }, { "sourceApplicationLicenceID", sourceApplicationLicenceID } }; string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "GetConversionStatus", additionalData); return new JsonNetResult { Data = new JsonBaseResult { Success = false, ErrorCode = "ERROR", Error = error } }; } } /// /// Search for active platform providers by (partial) legal or trading /// name. This is used by the Convert to E-hailing flow so that users /// can search by name instead of entering raw IDs. /// [HttpPost] public JsonNetResult SearchPlatformProviders(string searchTerm) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), Common.SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("#EXPOSE_ERROR#Security error"); } if (string.IsNullOrWhiteSpace(searchTerm)) { throw new Exception("#EXPOSE_ERROR#Please enter at least one character to search for a platform provider."); } searchTerm = searchTerm.Trim(); var db = new LegitimateDatabase(); // Limit to active providers and a small result set to keep the // dropdown manageable. var providers = db.Context.Database.SqlQuery( @"SELECT TOP 20 PlatformProviderID, LegalName, TradingName, CertificateNumber, Status FROM Verified.Vw_ProviderRegistry WHERE Status = 'Active' AND ( LegalName LIKE @p0 OR TradingName LIKE @p0 ) ORDER BY LegalName, TradingName", new object[] { "%" + searchTerm + "%" }).ToList(); return new JsonNetResult { Data = new JsonBaseResult { Success = true, Result = providers } }; } catch (Exception ex) { var additionalData = new Dictionary { { "searchTerm", searchTerm } }; string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "SearchPlatformProviders", additionalData); return new JsonNetResult { Data = new JsonBaseResult { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region DocumentPrecheckReceived [HttpPost] public JsonResult DocumentPrecheckReceived(long documentsPrecheckID, bool received) { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), SecurableEnum.ApplicationsModule_Home_StartNewApplication)) { throw new Exception("Security error"); } var applicationDatabase = new ApplicationDatabase(); var success = applicationDatabase.DocumentPrecheckReceivedUpdate(documentsPrecheckID, received); var results = new { Success = success, ErrorMessage = string.Empty }; return Json(results, JsonSerializerOptions.None); } #endregion } }