using Neo.Afx.Security; using Neo.Afx.Services.Integration; using Neo.Afx.ViewModels; using Neo.LegitimateLicences.ApplicationRequest.Models.Database; using Neo.LegitimateLicences.Common; using Neo.LegitimateLicences.Common.Helpers; using Neo.LegitimateLicences.Data.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using Neo.Afx.Services.Audits; using System.Data.Entity.Validation; using Neo.Afx.Services.Workflows.Entities; using Neo.Afx.Common; using Neo.LegitimateLicences.Logic.Helpers; using System.Web.Script.Serialization; using Neo.Afx.ComponentModel; using Neo.Afx.Mvc; namespace Neo.LegitimateLicences.ApplicationRequest { public partial class ApplicationRequestController { private static readonly JavaScriptSerializer _jsonSerializer = new JavaScriptSerializer { MaxJsonLength = int.MaxValue, RecursionLimit = 100 }; static ApplicationRequestController() { // Configure JSON serialization to handle circular references _jsonSerializer.RegisterConverters(new[] { new CircularReferenceResolver() }); } private class CircularReferenceResolver : JavaScriptConverter { public override IEnumerable SupportedTypes { get { return new[] { typeof(ApplicationLicence), typeof(ApplicationDetail), typeof(ApplicationReferral) }; } } public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) { var result = new Dictionary(); var type = obj.GetType(); foreach (var prop in type.GetProperties()) { // Skip navigation properties that could cause circular references if (prop.PropertyType.Name.Contains("ICollection") || prop.PropertyType.Name.Contains("ApplicationDetail") || prop.PropertyType.Name.Contains("ApplicationLicence") || prop.PropertyType.Name.Contains("ApplicationReferral")) { continue; } var value = prop.GetValue(obj); if (value != null) { result[prop.Name] = value; } } return result; } public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) { var instance = Activator.CreateInstance(type); foreach (var prop in type.GetProperties()) { if (dictionary.ContainsKey(prop.Name)) { var value = dictionary[prop.Name]; if (value != null) { // Handle type conversion if needed if (value.GetType() != prop.PropertyType) { value = Convert.ChangeType(value, prop.PropertyType); } prop.SetValue(instance, value); } } } return instance; } } #region Referrals /// /// Return View of all Referrals /// /// public ActionResult Referrals() { var isNew = WebHelper.ItemID == -1; var itemId = WebHelper.ItemID; var taskId = WebHelper.TaskID; #region Get active user task Vw_WorkflowInstanceTask activeUserTask = null; if (taskId != -1) { activeUserTask = WorkflowHelper.GetActiveUserUserTaskByID((long)EntityEnum.ApplicationRequestDetails, itemId, taskId, Profile.UserID); } if (activeUserTask == null) { activeUserTask = WorkflowHelper.GetActiveUserTask(Profile.UserID, EntityEnum.ApplicationRequestDetails, itemId); } #endregion var model = new ApplicationRequestFormModel { UserSecurables = (Profile.Securables != null) ? Profile.Securables.ToList() : new List(), Ui = new WorkflowConsoleUIProperties() { canSave = (activeUserTask != null && activeUserTask.WorkflowTemplateStepNumber == 12) } }; var applicationDatabase = new ApplicationDatabase(); var applicationReferral = applicationDatabase.GetApplicationReferrals(itemId, Profile.UserID); applicationReferral.Referrals = applicationReferral.Referrals.Where(a => !a.IsCancelled).ToList(); // Create a dictionary for the custom serialization var customData = new Dictionary(); // Copy all properties from applicationReferral foreach (var prop in applicationReferral.GetType().GetProperties()) { var value = prop.GetValue(applicationReferral); if (value != null) { if (prop.Name == "Referrals") { // Special handling for Referrals collection var referrals = applicationReferral.Referrals; if (referrals != null && referrals.Count > 0) { var serializedReferrals = new List>(); foreach (var referral in referrals) { var referralDict = new Dictionary(); // Get all properties from the referral foreach (var refProp in referral.GetType().GetProperties()) { // Skip navigation properties that could cause circular references if (refProp.PropertyType.Name.Contains("ICollection") || refProp.PropertyType.Name.Contains("ApplicationDetail")) { continue; } var refValue = refProp.GetValue(referral); if (refValue != null) { if (refProp.Name == "ReferralType" && referral.ReferralType != null) { var rtDict = new Dictionary(); rtDict["ReferralTypeID"] = referral.ReferralType.ReferralTypeID; rtDict["Description"] = referral.ReferralType.Description; referralDict["ReferralType"] = rtDict; } else if (refProp.Name == "ApplicationLicence" && referral.ApplicationLicence != null) { var alDict = new Dictionary(); if (referral.ApplicationLicence.ApplicationLicenceID > 0) alDict["ApplicationLicenceID"] = referral.ApplicationLicence.ApplicationLicenceID; if (!string.IsNullOrEmpty(referral.ApplicationLicence.ApplicationLicenceReferenceNumber)) alDict["ApplicationLicenceReferenceNumber"] = referral.ApplicationLicence.ApplicationLicenceReferenceNumber; referralDict["ApplicationLicence"] = alDict; } else { referralDict[refProp.Name] = refValue; } } } serializedReferrals.Add(referralDict); } customData["Referrals"] = serializedReferrals; } else { customData["Referrals"] = new List>(); } } else { customData[prop.Name] = value; } } } // Use the JavaScriptSerializer directly on our custom dictionary model.Data = _jsonSerializer.Serialize(customData); model.ApplicationView = applicationDatabase.GetApplicationView(itemId, Profile.UserID); model.Lookups = GetLookupsForFormGetLookupsFormView(); model.WorkflowInstance = WorkflowHelper.GetWorkflowInstanceView(WebHelper.EntityID, WebHelper.ItemID, Profile.UserID); return View("Referrals", model); } #endregion #region Referral /// /// Dialog to capture Referral details /// /// /// /// public ActionResult Referral(long applicationDetailID, long applicationReferralDetailID) { var applicationDatabase = new ApplicationDatabase(); var model = new ApplicationReferalModel { UserSecurables = (Profile.Securables != null) ? Profile.Securables.ToList() : new List(), ApplicationReferral = applicationDatabase.GetApplicationReferral(applicationReferralDetailID, applicationDetailID, Profile.UserID), ApplicationDetailID = applicationDetailID }; model.Lookups = GetLookupsForReferral(applicationDetailID.ToString()); return View("Referrals.Referral", model); } #endregion #region GetLookupsForReferral /// /// Look list uniquie for Referral( /// /// public List GetLookupsForReferral(string applicationDetailID) { var lookups = new List(); var integrationStore = new SqlIntegrationStore(); try { UserProfileHelper userProfileHelper = new UserProfileHelper(Profile.UserID, Profile.OfficeLocationID); var officeLocation = userProfileHelper.OfficeLocation; integrationStore.Open(); if (userProfileHelper.IsNPTR) { lookups.Add(new LookupList("ReferralTypes", integrationStore.GetDataEntities("ReferralTypes", string.Empty).OrderBy(a => a.Title))); lookups.Add(new LookupList("ReferralAddress", integrationStore.GetDataEntities("ReferralAddress", string.Empty) .Where(x => x.Properties["referraltypeid"] == "3").OrderBy(a => a.Title))); } else { lookups.Add(new LookupList("ReferralTypes", integrationStore.GetDataEntities("ReferralTypes", string.Empty).Where(x => x.Key == "2").OrderBy(a => a.Title))); lookups.Add(new LookupList("ReferralAddress", integrationStore.GetDataEntities("ReferralAddress", string.Empty).Where(x => x.Properties["provinceid"] == officeLocation.ProvinceID.ToString()).OrderBy(a => a.Title))); } lookups.Add(new LookupList("ApplicationLicences", integrationStore.GetDataEntities("ApplicationLicences", "ApplicationDetailID=" + applicationDetailID).OrderBy(a => a.Title))); } finally { integrationStore.Close(); } return lookups; } #endregion #region SaveApplicationReferral /// /// Save Application Referral /// /// /// /// [HttpPost] public JsonNetResult SaveApplicationReferral(long applicationDetailID, ApplicationReferral value) { var changes = new List(); var auditDb = new AuditsDatabase(); var appDb = new ApplicationDatabase(); //don't use database context as we need the values refreshed every time try { #region Check if can update var model = GetModel(); if (!model.CanEditReferralsDetails) { throw new Exception("Security error"); } #endregion var existingModel = appDb.GetApplicationReferral(value.ApplicationReferralDetailID, applicationDetailID, Profile.UserID); if(value.ApplicationReferralDetailID > 0) { Database.Update(value); changes.AddRange(auditDb.GetEntityDifferences(existingModel, value, "ApplicationReferralDetailID")); } else { Database.Insert(value); changes.AddRange(auditDb.GetEntityDifferences(existingModel, value, "ApplicationReferralDetailID")); } Database.Save(); if (changes.Count > 0) { auditDb.WriteEntries(2 /*Application*/, 2 /*Updated*/, changes, (short)EntityEnum.ApplicationtDetails, 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 return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } #region Clean data on return value.ReferralType = appDb.GetReferralType(value.ReferralTypeID); #endregion return new JsonNetResult() { Data = new JsonBaseResult() { Success = true, Result = value } }; } #endregion #region DeleteApplicationReferral /// /// Cancel Application Referral /// /// /// /// [HttpPost] public JsonNetResult DeleteApplicationReferral(long applicationDetailID, ApplicationReferral value) { var changes = new List(); var auditDb = new AuditsDatabase(); try { #region Check if can save var model = GetModel(); if (!model.CanEditReferralsDetails) { throw new Exception("Security error"); } #endregion var projDb = new ApplicationDatabase(); //don't use database context as we need the values refreshed every time var existingModel = projDb.GetApplicationReferral(value.ApplicationReferralDetailID, applicationDetailID, Profile.UserID); if (value.ApplicationReferralDetailID > 0) { value.IsCancelled = true; Database.Update(value); changes.AddRange(auditDb.GetEntityDifferences(existingModel, value, "ApplicationReferralDetailID")); } Database.Save(); if (changes.Count > 0) { auditDb.WriteEntries(2 /*Application*/, 2 /*Updated*/, changes, (short)EntityEnum.ApplicationtDetails, 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 return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = error } }; } return new JsonNetResult() { Data = new JsonBaseResult() { Success = true } }; } #endregion } }