using System; using System.Linq; using System.Web.Mvc; using System.Data.Entity.Validation; using System.Collections.Generic; using Neo.Afx.Services.Workflows; using Neo.LegitimateLicences.Data.Models; using Neo.Afx.Services.Audits; using Neo.LegitimateLicences.ApplicationRequest.Models.Database; using Neo.Afx.Common; using Neo.LegitimateLicences.Common; namespace Neo.LegitimateLicences.ApplicationRequest { public partial class ApplicationRequestController { #region Save /// /// Save application form data /// /// /// [HttpPost] public JsonNetResult Save(ApplicationDetail value) { var changes = new List(); var auditDb = new AuditsDatabase(); try { if (value.ApplicationDetailID <= 0) { changes.Add("New application created"); value.CreatedDate = DateTime.Now; value.CreatedByID = Profile.UserID; value.UpdatedDate = DateTime.Now; value.UpdatedByID = Profile.UserID; #region Applicant var appDb = new ApplicationDatabase(); //don't use database context as we need the values refreshed every time var existingModel = appDb.GetApplicationForm(value.ApplicationDetailID, Profile.UserID); changes.AddRange(auditDb.GetEntityDifferences(existingModel.Applicant, value.Applicant, "ApplicationDetailID")); #endregion Database.Insert(value); } else { #region Check if can save var model = GetModel(); if (!model.Ui.canSubmit) { throw new Exception("Security error"); } #endregion var appDb = new ApplicationDatabase(); //don't use database context as we need the values refreshed every time var existingModel = appDb.GetApplicationForm(value.ApplicationDetailID, Profile.UserID); value.UpdatedDate = DateTime.Now; value.UpdatedByID = Profile.UserID; #region Preserve provider Payment requirement // Ensure provider registrations (60/61/62) always require payment. // Use the persisted ApplicationRequestTypeID (existingModel) in case the posted payload omits it. if (existingModel != null && (existingModel.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration || existingModel.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal || existingModel.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions)) { value.IsReceiptRequired = true; } #endregion #region Update ApplicationDetail, ApplicationApplicantDetail, ApplicationPreviousLicenceHolder, ApplicationContractDetail, ApplicationNPTRDetail, ApplicationProxyDetail Details Database.Update(value); changes.AddRange(auditDb.GetEntityDifferences(existingModel, value, "ApplicationDetailID")); Database.Update(value.Applicant); changes.AddRange(auditDb.GetEntityDifferences(existingModel.Applicant, value.Applicant, "ApplicationDetailID")); Database.Update(value.PreviousLicenceHolder); changes.AddRange(auditDb.GetEntityDifferences(existingModel.PreviousLicenceHolder, value.PreviousLicenceHolder, "ApplicationDetailID")); Database.Update(value.Contract); changes.AddRange(auditDb.GetEntityDifferences(existingModel.Contract, value.Contract, "ApplicationDetailID")); // // Compute NPTR totals before save // if (value != null && value.NPTR != null) // { int existingTotal = (value.NPTR.TotalMotorcar ?? 0) + (value.NPTR.TotalMinibus ?? 0) + (value.NPTR.TotalMidibus ?? 0) + (value.NPTR.TotalBus ?? 0) + (value.NPTR.TotalOther ?? 0); int newTotal = (value.NPTR.NewTotalMotorcar ?? 0) + (value.NPTR.NewTotalMinibus ?? 0) + (value.NPTR.NewTotalMidibus ?? 0) + (value.NPTR.NewTotalBus ?? 0) + (value.NPTR.NewTotalOther ?? 0); // Persist computed totals value.NPTR.TotalVehicles = existingTotal; value.NPTR.TotalVehiclesToBePurchased = newTotal; // // Server-side guard: require at least 1 vehicle across Existing or New // if ((existingTotal + newTotal) <= 0) // { // throw new Exception("Validation error: At least one vehicle is required in Existing or New."); // } // } Database.Update(value.NPTR); changes.AddRange(auditDb.GetEntityDifferences(existingModel.NPTR, value.NPTR, "ApplicationDetailID")); Database.Update(value.Proxy); changes.AddRange(auditDb.GetEntityDifferences(existingModel.Proxy, value.Proxy, "ApplicationDetailID")); #endregion } } catch (Exception ex) { #region Error Handling #region Error Additional Data Dictionary additionalData = new Dictionary(); additionalData.Add("ApplicationDetailID", value.ApplicationDetailID); #endregion string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "Save", additionalData); #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error =string.Format("Error: {0}", error) } }; } try { // Final enforcement: ensure provider apps always require receipt before commit try { var appDbFinal = new ApplicationDatabase(); var persisted = appDbFinal.GetApplicationForm(value.ApplicationDetailID, Profile.UserID); if (persisted != null && (persisted.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration || persisted.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal || persisted.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions) && persisted.IsReceiptRequired == false) { persisted.IsReceiptRequired = true; Database.Update(persisted); } } catch {} Database.Save(); WorkflowsDatabase workflowsDatabase = new WorkflowsDatabase(); workflowsDatabase.ExecutePostFormSave(value.WorkflowInstanceID.Value, Profile.UserID); // Post-hook: some workflow post-save logic recalculates rules. Re-enforce for provider types. try { var appDbPost = new ApplicationDatabase(); var persistedPost = appDbPost.GetApplicationForm(value.ApplicationDetailID, Profile.UserID); if (persistedPost != null && (persistedPost.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistration || persistedPost.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationRenewal || persistedPost.ApplicationRequestTypeID == (short)ApplicationRequestTypeEnum.NPTR_EhailingProviderRegistrationAmendConditions) && persistedPost.IsReceiptRequired == false) { // Use direct SQL to avoid any EF tracking or concurrency issues var dbRaw = new LegitimateDatabase(); dbRaw.Context.Database.ExecuteSqlCommand( "UPDATE App.ApplicationDetails SET IsReceiptRequired = 1 WHERE ApplicationDetailID = @p0 AND ApplicationRequestTypeID IN (60,61,62)", new System.Data.SqlClient.SqlParameter("@p0", value.ApplicationDetailID)); } } catch {} if (changes.Count > 0) { auditDb.WriteEntries((short)AuditSourceEnum.Application, (short)AuditActionEnum.Updated, changes, (short)EntityEnum.ApplicationtDetails, value.ApplicationDetailID, Profile.UserID); } } catch (DbEntityValidationException dbEx) { foreach (var validationError in dbEx.EntityValidationErrors.SelectMany(validationErrors => validationErrors.ValidationErrors)) { return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error =string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) } }; } } catch (Exception ex) { #region Error Handling #region Error Additional Data Dictionary additionalData = new Dictionary(); additionalData.Add("ApplicationDetailID", value.ApplicationDetailID); #endregion string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "Save", additionalData); #endregion if (ex.InnerException != null) { if (ex.InnerException.Message.Contains("IX_PrecheckDetailID")) { return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = "The application has already been saved against this pre-check. Please submit the original application instead." } }; } else { return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = string.Format("Error: {0}", error) } }; } } else { return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = string.Format("Error: {0}", error) } }; } } var formDb = new ApplicationDatabase(); var formData = formDb.GetApplicationForm(value.ApplicationDetailID, Profile.UserID); return new JsonNetResult() { Data = new JsonBaseResult() { Result = formData, Success = true } }; } #endregion #region IssueProviderCertificate [HttpPost] public JsonNetResult IssueProviderCertificate(long applicationDetailID) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), SecurableEnum.ApplicationsModule_Adjudication_Console_ApproveDecisions)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var appDb = new ApplicationDatabase(); var info = appDb.IssueProviderCertificate(applicationDetailID, Profile.UserID); // Notification: certificate issued try { var db = new LegitimateDatabase(); var templateId = db.Context.Database.SqlQuery( "SELECT TOP 1 MessageTemplateID FROM Crm.MessageTemplates WHERE MessageTemplateKey = @p0", new object[] { "APP_PROVIDER_CERT_ISSUED" } ).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 = info } }; } catch (Exception ex) { string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "IssueProviderCertificate"); return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion #region ReissueProviderCertificate [HttpPost] public JsonNetResult ReissueProviderCertificate(long applicationDetailID, string reason) { try { if (!SecurityHelper.UserHasAccessToSecurable(Profile.Securables.ToList(), SecurableEnum.ApplicationsModule_Adjudication_Console_ApproveDecisions)) { throw new Exception("#EXPOSE_ERROR#Security error"); } var appDb = new ApplicationDatabase(); var info = appDb.ReissueProviderCertificate(applicationDetailID, reason, Profile.UserID); // Notification: certificate reissued try { var db = new LegitimateDatabase(); var templateId = db.Context.Database.SqlQuery( "SELECT TOP 1 MessageTemplateID FROM Crm.MessageTemplates WHERE MessageTemplateKey = @p0", new object[] { "APP_PROVIDER_CERT_REISSUED" } ).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 = info } }; } catch (Exception ex) { string error = ErrorHelper.ProcessError(ex, "ApplicationRequest", "ReissueProviderCertificate"); return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } } #endregion } }