using Neo.Afx.Mvc; using Neo.Afx.Common; using Neo.Afx.Security; using Neo.Afx.Services.Workflows.Entities; using Neo.LegitimateLicences.Common; using Neo.LegitimateLicences.Common.Helpers; using Neo.LegitimateLicences.Common.ViewModels; using Neo.LegitimateLicences.Data.Models; using Neo.LegitimateLicences.AppProviderIssueRequest.Models.Database; using System; using System.Linq; using System.Web.Mvc; using System.Collections.Generic; namespace Neo.LegitimateLicences.AppProviderIssueRequest { public partial class AppProviderIssueRequestController : Neo.LegitimateLicences.Common.ControllerBase { private AppProviderIssueDatabase Database = new AppProviderIssueDatabase(); private class WorkflowLink { public int EntityID { get; set; } public long ItemID { get; set; } public long WorkflowInstanceID { get; set; } public string ReferenceNumber { get; set; } public double? Step { get; set; } } /// /// Resolves AppProviderIssueDetailID from PlatformProviderID (for backward compatibility) /// private long? ResolveAppProviderIssueDetailID(long platformProviderID) { var db = new LegitimateDatabase(); var result = db.Context.Database.SqlQuery( @"SELECT TOP 1 APID.AppProviderIssueDetailID FROM App.AppProviderIssueDetails APID INNER JOIN Verified.ProviderCertificates PC ON PC.ProviderCertificateID = APID.VerifiedProviderCertificateID WHERE PC.PlatformProviderID = @p0 ORDER BY APID.CreatedDate DESC", new object[] { platformProviderID }).FirstOrDefault(); return result; } /// /// Resolves issuing workflow for AppProviderIssueDetailID (EntityID 1042) /// private WorkflowLink ResolveAppProviderIssueWorkflow(long appProviderIssueDetailID) { var db = new LegitimateDatabase(); var sql = @" SELECT TOP 1 CAST(1042 AS INT) AS EntityID, /*AppProviderIssueRequest*/ APID.AppProviderIssueDetailID AS ItemID, WI.WorkflowInstanceID, WI.ReferenceNumber, WTS.Step FROM App.AppProviderIssueDetails APID LEFT JOIN Wf.WorkflowInstances WI ON WI.WorkflowInstanceID = APID.WorkflowInstanceID LEFT JOIN Wf.WorkflowTemplateSteps WTS ON WTS.WorkflowTemplateStepID = WI.WorkflowTemplateStepID WHERE APID.AppProviderIssueDetailID = @AppProviderIssueDetailID"; return db.Context.Database.SqlQuery(sql, new System.Data.SqlClient.SqlParameter("@AppProviderIssueDetailID", appProviderIssueDetailID)).FirstOrDefault(); } /// /// Legacy method: Resolves application workflow from PlatformProviderID (for backward compatibility) /// private WorkflowLink ResolveProviderWorkflow(long platformProviderID) { var db = new LegitimateDatabase(); var sql = @" SELECT TOP 1 CAST(1000 AS INT) AS EntityID, /*Applications*/ AD.ApplicationDetailID AS ItemID, WI.WorkflowInstanceID, WI.ReferenceNumber, WTS.Step FROM App.ApplicationDetails AD INNER JOIN App.ApplicationApplicantDetails AAD ON AAD.ApplicationDetailID = AD.ApplicationDetailID INNER JOIN Wf.WorkflowInstances WI ON WI.WorkflowInstanceID = AD.WorkflowInstanceID INNER JOIN Wf.WorkflowTemplateSteps WTS ON WTS.WorkflowTemplateStepID = WI.WorkflowTemplateStepID INNER JOIN Verified.PlatformProviders PP ON PP.PlatformProviderID = @PlatformProviderID WHERE AD.ApplicationRequestTypeID IN (60,61,62) /*App provider request types*/ AND ( (NULLIF(LTRIM(RTRIM(PP.BusinessRegNumber)), '') IS NOT NULL AND LTRIM(RTRIM(ISNULL(AAD.IDNumberOrBusinessRegistrationNo, ''))) = LTRIM(RTRIM(PP.BusinessRegNumber))) OR (NULLIF(LTRIM(RTRIM(PP.TradingName)), '') IS NOT NULL AND LTRIM(RTRIM(ISNULL(AAD.TradeName, ''))) = LTRIM(RTRIM(PP.TradingName))) OR (NULLIF(LTRIM(RTRIM(PP.LegalName)), '') IS NOT NULL AND LTRIM(RTRIM(ISNULL(AAD.SurnameOrCompanyName, ''))) = LTRIM(RTRIM(PP.LegalName))) ) ORDER BY WI.UpdatedDate DESC, WI.CreatedDate DESC"; return db.Context.Database.SqlQuery(sql, new System.Data.SqlClient.SqlParameter("@PlatformProviderID", platformProviderID)).FirstOrDefault(); } private class ProviderSummary { public long PlatformProviderID { get; set; } public string LegalName { get; set; } public string TradingName { get; set; } public string BusinessRegNumber { get; set; } public string CertificateNumber { get; set; } public System.DateTime? IssuedAt { get; set; } public System.DateTime? ExpiresAt { get; set; } } [HttpGet] public ActionResult Console(long itemID) { // Security same as accreditation style var securables = (Profile != null && Profile.Securables != null) ? Profile.Securables.ToList() : null; var canAccess = Profile.IsNPTR || SecurityHelper.UserHasAccessToSecurable(securables, SecurableEnum.ApplicationsModule); if (!canAccess) { return RedirectToAction("ShowError", "Error", new { msg = "Security error" }); } // Determine if itemID is AppProviderIssueDetailID or PlatformProviderID // Try to resolve as AppProviderIssueDetailID first (issuing workflow) var appProviderIssueDetailID = itemID; var linkCtx = ResolveAppProviderIssueWorkflow(appProviderIssueDetailID); // If not found, try to resolve from PlatformProviderID (backward compatibility) if (linkCtx == null) { var resolvedID = ResolveAppProviderIssueDetailID(itemID); if (resolvedID.HasValue) { appProviderIssueDetailID = resolvedID.Value; linkCtx = ResolveAppProviderIssueWorkflow(appProviderIssueDetailID); } } // Get AppProviderIssueDetails view var appProviderIssueView = Database.GetAppProviderIssueView(appProviderIssueDetailID, Profile.UserID); if (appProviderIssueView == null) { return RedirectToAction("ShowError", "Error", new { msg = "App Provider Issue Details not found" }); } // Sidepane context: Use related application workflow for sidepane // Get PlatformProviderID from the certificate to resolve application workflow var db = new LegitimateDatabase(); var platformProviderID = db.Context.Database.SqlQuery( @"SELECT PC.PlatformProviderID FROM Verified.ProviderCertificates PC WHERE PC.ProviderCertificateID = @p0", new object[] { appProviderIssueView.VerifiedProviderCertificateID }).FirstOrDefault(); if (platformProviderID.HasValue) { var appLink = ResolveProviderWorkflow(platformProviderID.Value); if (appLink != null) { ViewBag.SidepaneEntityID = appLink.EntityID; ViewBag.SidepaneItemID = appLink.ItemID; } } ViewBag.Controller = "App Provider"; ViewBag.Page = "Provider Console"; ViewBag.AppProviderIssueView = appProviderIssueView; // Populate ViewBag.Provider for Console view (similar to GetConsoleData) if (platformProviderID.HasValue) { var provider = db.Context.Database.SqlQuery( @"SELECT PP.PlatformProviderID, PP.LegalName, PP.TradingName, PP.BusinessRegNumber, VC.CertificateNumber, VC.IssuedAt, VC.ExpiresAt FROM Verified.PlatformProviders PP OUTER APPLY ( SELECT TOP 1 CertificateNumber, IssuedAt, ExpiresAt FROM Verified.ProviderCertificates PC WHERE PC.PlatformProviderID = PP.PlatformProviderID ORDER BY PC.IssuedAt DESC ) VC WHERE PP.PlatformProviderID = @p0", new object[] { platformProviderID.Value }).FirstOrDefault(); ViewBag.Provider = provider; } // Get workflow instance for issuing workflow (EntityID 1042) var workflowInstance = (linkCtx != null && linkCtx.WorkflowInstanceID > 0) ? WorkflowHelper.GetWorkflowInstanceView(1042, appProviderIssueDetailID, Profile.UserID) : null; // Get active user task (EntityID 1042) Vw_WorkflowInstanceTask activeUserTask = null; if (linkCtx != null && linkCtx.WorkflowInstanceID > 0) { activeUserTask = WorkflowHelper.GetActiveUserTask(Profile.UserID, 1042, appProviderIssueDetailID); } var model = new ResponsiveAppWorkflowModel { Ui = new Neo.Afx.ViewModels.WorkflowConsoleUIProperties { canSubmit = (activeUserTask != null && activeUserTask.WorkflowTemplateStepTypeID == (short)WorkflowTemplateStepTypeEnum.DataCapture), canViewDocuments = true, canViewForm = true, canViewComments = true, canViewTasks = true, canViewCorrespondence = true, canApproveReject = (activeUserTask != null && activeUserTask.WorkflowTemplateStepTypeID == (short)WorkflowTemplateStepTypeEnum.Approval), canRequestCorrection = (activeUserTask != null && activeUserTask.WorkflowTemplateStepNumber > 1), canDelete = (activeUserTask != null) } }; return View("Console", model); } // StartPrintout method moved to AppProviderIssueRequestController.Printing.cs // This duplicate method has been removed to resolve ambiguity [HttpGet] public JsonNetResult GetDashboardData(long itemID) { try { var link = ResolveProviderWorkflow(itemID); if (link == null) { return new JsonNetResult { Data = new { Success = false, Error = "No related application found." }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } return new JsonNetResult { Data = new { Success = true, Result = link }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } catch (Exception ex) { return new JsonNetResult { Data = new { Success = false, Error = ex.Message }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } } [HttpGet] public JsonNetResult GetPlatformProviderID(long appProviderIssueDetailID) { try { var db = new LegitimateDatabase(); var platformProviderID = db.Context.Database.SqlQuery( @"SELECT TOP 1 PC.PlatformProviderID FROM App.AppProviderIssueDetails APID INNER JOIN Verified.ProviderCertificates PC ON PC.ProviderCertificateID = APID.VerifiedProviderCertificateID WHERE APID.AppProviderIssueDetailID = @p0 AND APID.IsCancelled = 0", new object[] { appProviderIssueDetailID }).FirstOrDefault(); if (!platformProviderID.HasValue) { return new JsonNetResult { Data = new { Success = false, Error = "PlatformProviderID not found for this App Provider Issue Request." }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } return new JsonNetResult { Data = new { Success = true, Result = new { PlatformProviderID = platformProviderID.Value } }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } catch (Exception ex) { return new JsonNetResult { Data = new { Success = false, Error = ex.Message }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } } [HttpGet] public JsonNetResult GetPrintingContext(long itemID) { try { var link = ResolveProviderWorkflow(itemID); if (link == null) { return new JsonNetResult { Data = new { Success = false, Error = "No related application found." }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } var wd = new Neo.Afx.Services.Workflows.WorkflowsDatabase(); var at = WorkflowHelper.GetActiveUserTask(Profile.UserID, link.EntityID, link.ItemID); var canAssignToSelf = false; if (at == null) { // Get any outstanding task and check if can assign to me var wi = wd.GetWorkflowInstance(link.EntityID, link.ItemID); var nextOutstanding = wi.WorkflowInstanceTasks.FirstOrDefault(t => t.WorkflowInstanceTaskStatusID == 1 /*outstanding*/); if (nextOutstanding != null) { canAssignToSelf = wd.WorkflowInstanceTaskCanAssignToMe(nextOutstanding.WorkflowInstanceTaskID, Profile.UserID); } } var assignedToMe = (at != null); return new JsonNetResult { Data = new { Success = true, Result = new { link.EntityID, link.ItemID, AssignedToMe = assignedToMe, CanAssignToSelf = canAssignToSelf } }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } catch (Exception ex) { return new JsonNetResult { Data = new { Success = false, Error = ex.Message }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } } [HttpPost] public JsonNetResult AssignTaskToMe(long itemID) { try { var link = ResolveProviderWorkflow(itemID); if (link == null) { return new JsonNetResult { Data = new { Success = false, Error = "No related application found." } }; } var wd = new Neo.Afx.Services.Workflows.WorkflowsDatabase(); var wi = wd.GetWorkflowInstance(link.EntityID, link.ItemID); var nextOutstanding = wi.WorkflowInstanceTasks.FirstOrDefault(t => t.WorkflowInstanceTaskStatusID == 1 /*outstanding*/); if (nextOutstanding == null) { return new JsonNetResult { Data = new { Success = false, Error = "No outstanding task to assign." } }; } var canAssign = wd.WorkflowInstanceTaskCanAssignToMe(nextOutstanding.WorkflowInstanceTaskID, Profile.UserID); if (!canAssign) { return new JsonNetResult { Data = new { Success = false, Error = "You cannot assign this task to yourself." } }; } wd.ReAssignWorkflowInstanceTask(nextOutstanding.WorkflowInstanceTaskID, Profile.UserID, "Self-assigned", User.Identity.Name); return new JsonNetResult { Data = new { Success = true } }; } catch (Exception ex) { return new JsonNetResult { Data = new { Success = false, Error = ex.Message } }; } } [HttpGet] public JsonNetResult GetConsoleData(long itemID) { try { var db = new LegitimateDatabase(); // Resolve PlatformProviderID from AppProviderIssueDetailID var platformProviderID = db.Context.Database.SqlQuery( @"SELECT TOP 1 PC.PlatformProviderID FROM App.AppProviderIssueDetails APID INNER JOIN Verified.ProviderCertificates PC ON PC.ProviderCertificateID = APID.VerifiedProviderCertificateID WHERE APID.AppProviderIssueDetailID = @p0", new object[] { itemID }).FirstOrDefault(); if (!platformProviderID.HasValue) { return new JsonNetResult { Data = new { Success = false, Error = "Provider certificate not found for this issue request." }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } var provider = db.Context.Database.SqlQuery( @"SELECT PP.PlatformProviderID, PP.LegalName, PP.TradingName, PP.BusinessRegNumber, VC.CertificateNumber, VC.IssuedAt, VC.ExpiresAt FROM Verified.PlatformProviders PP OUTER APPLY ( SELECT TOP 1 CertificateNumber, IssuedAt, ExpiresAt FROM Verified.ProviderCertificates PC WHERE PC.PlatformProviderID = PP.PlatformProviderID ORDER BY PC.IssuedAt DESC ) VC WHERE PP.PlatformProviderID = @p0", new object[] { platformProviderID.Value }).FirstOrDefault(); var wf = db.Context.Database.SqlQuery( @"SELECT Wi.WorkflowInstanceID, Wi.ReferenceNumber, Wi.Description AS WorkflowInstanceDescription, Wts.StepTitle AS CurrentStepTitle, Wts.Step FROM Wf.WorkflowInstances Wi INNER JOIN Wf.WorkflowTemplateSteps Wts ON Wts.WorkflowTemplateStepID = Wi.WorkflowTemplateStepID WHERE Wi.EntityID = @p0 AND Wi.ItemID = @p1", new object[] { (int)EntityEnum.AppProviderIssueRequest, itemID }).FirstOrDefault(); // Determine whether any non-test Provider Certificate print exists for this provider var hasNonTestPrint = db.Context.Database.SqlQuery( @"SELECT TOP 1 1 FROM Verified.Printouts WHERE EntityID = @p0 AND ItemID = @p1 AND PrintoutTypeID = 8 AND ISNULL(IsTestPrint,0) = 0", new object[] { (int)EntityEnum.PlatformProviders, platformProviderID.Value }).Any(); return new JsonNetResult { Data = new { Success = true, Result = new { Provider = provider, Workflow = wf, HasNonTestPrint = hasNonTestPrint } }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } catch (Exception ex) { return new JsonNetResult { Data = new { Success = false, Error = ex.Message }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } } } }