using Neo.Afx.ComponentModel; using Neo.Afx.Mvc; using Neo.Afx.Security; using Neo.Afx.Services.Audits; using Neo.Afx.Services.Integration; using Neo.Afx.Services.Notifications.Entities; using Neo.Afx.Services.Workflows; using Neo.Afx.Services.Workflows.Entities; 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.Data.Entity.Validation; using System.Linq; using System.Web; using System.Web.Mvc; using Neo.LegitimateLicences.Logic.ApplicationLogic; using Neo.Afx.Common; using Neo.LegitimateLicences.Logic.Helpers; namespace Neo.LegitimateLicences.ApplicationRequest { public partial class ApplicationRequestController { #region LicenceServiceDetails public ActionResult LicenceServiceDetails(long applicationDetailID, long applicationLicenceID) { #region Get active user task Vw_WorkflowInstanceTask activeUserTask = null; activeUserTask = WorkflowHelper.GetActiveUserTask(Profile.UserID, EntityEnum.ApplicationRequestDetails, applicationDetailID); #endregion var model = new ApplicationRequestFormModel { UserSecurables = (Profile.Securables != null) ? Profile.Securables.ToList() : new List(), Ui = new WorkflowConsoleUIProperties() }; var applicationDatabase = new ApplicationDatabase(); var serviceDetails = applicationDatabase.GetLicenceServiceDetails(applicationLicenceID, Profile.UserID); var application = applicationDatabase.GetApplicationView(applicationDetailID, Profile.UserID); model.Data = serviceDetails; model.ApplicationView = applicationDatabase.GetApplicationView(applicationDetailID, Profile.UserID); model.Lookups = GetServiceDetailLookups(); model.WorkflowInstance = WorkflowHelper.GetWorkflowInstanceView(WebHelper.EntityID, WebHelper.ItemID, Profile.UserID); if (model.ApplicationView.CopiedFromApplicationDetailID != null) { model.ParentApplicationView = Database.GetApplicationView(model.ApplicationView.CopiedFromApplicationDetailID.Value, Profile.UserID); } else { model.ParentApplicationView = new Neo.LegitimateLicences.ApplicationRequest.Models.Database.Vw_ApplicationDetails_Light(); } #region Get Vehicle/Service Types ApplicationLogic applicationLogic = new ApplicationLogic(); model.VehicleServiceTypeCollection = applicationLogic.VehicleServiceTypeCollectionGet(); #endregion model.SetFormEditState(activeUserTask); return View("Licences.ServiceDetails", model); } #endregion #region GetLookups public List GetServiceDetailLookups() { 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("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("VehicleTypes", integrationStore.GetDataEntities("VehicleTypes", string.Empty).OrderBy(a => a.Title))); } finally { integrationStore.Close(); } return lookups; } #endregion #region SaveLicenceServiceDetails [HttpPost] public JsonNetResult SaveLicenceServiceDetails(ApplicationLicence value) { var changes = new List(); var auditDb = new AuditsDatabase(); try { #region Check if can save var model = GetModel(); if (!model.CanEditServiceTypeDetails) { 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.GetLicenceServiceDetails(value.ApplicationLicenceID, Profile.UserID); ////if (existingModel != null && existingModel.UpdatedDate.ToLongTimeString() != value.UpdatedDate.ToLongTimeString()) ////{ //// return new JsonNetResult() //// { //// Data = new JsonBaseResult() //// { //// Success = false, //// ErrorCode = "CONFLICT", //// Error ="The record has been modified by someone else. Please try again." //// } //// }; ////} #region Check if user is allowed to edit the record at this stage ////try ////{ //// projDb.CheckSecurity(value.ApplicationRequestDetailID, "Save", Profile.UserID); ////} ////catch (Exception ex) ////{ //// return Json(new //// { //// Result = "ERROR", //// Message = new LegitimateDatabase().GetInnermostMessage(ex) //// }); ////} #endregion //value.UpdatedDate = DateTime.Now; //value.UpdatedByID = Profile.UserID; #region value.Services - Option B: Delete All + Recreate All // Step 1: Log all existing services for audit trail before deletion foreach (var existingService in existingModel.Services) { changes.Add(string.Format("{0}, Removed service type {1} (Delete All + Recreate)", "ApplicationLicenceServiceDetails", existingService.ServiceTypeID)); var blankObj = new ApplicationLicenceServiceDetail(); changes.AddRange(auditDb.GetEntityDifferences(existingService, blankObj, "ApplicationLicenceServiceDetailID")); } // Step 2: Delete all existing service records for this licence // Convert to list to avoid collection modification during enumeration var servicesToDelete = existingModel.Services.ToList(); foreach (var existingService in servicesToDelete) { Database.Context.Entry(existingService).State = System.Data.Entity.EntityState.Deleted; } // Step 3: Create new records for all selected service types foreach (var service in value.Services) { service.ServiceType = null; service.ApplicationLicenceServiceDetailID = 0; // Ensure it's treated as new record Database.Insert(service); var blankObj = new ApplicationLicenceServiceDetail(); changes.Add(string.Format("{0}, Added service type {1} (Recreate)", "ApplicationLicenceServiceDetails", service.ServiceTypeID)); changes.AddRange(auditDb.GetEntityDifferences(blankObj, service, "ApplicationLicenceServiceDetailID")); } // Step 4: Update only the main ApplicationLicence entity properties (not the Services collection) // We need to update the existing entity in the context, not the one passed from the client var existingLicence = Database.Context.Set().Find(value.ApplicationLicenceID); if (existingLicence != null) { // Update only the properties that might have changed (like VehicleTypeID) existingLicence.VehicleTypeID = value.VehicleTypeID; //existingLicence = DateTime.Now; //existingLicence.UpdatedByID = Profile.UserID; changes.AddRange(auditDb.GetEntityDifferences(existingModel, existingLicence, "ApplicationLicenceID")); } #endregion Database.Save(); if (changes.Count > 0) { auditDb.WriteEntries(2 /*Application*/, 2 /*Updated*/, changes, 1000 /*ApplicationRequestDetails*/, 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) { return new JsonNetResult() { Data = new JsonBaseResult() { Success = false, ErrorCode = "ERROR", Error = string.Format("Error: {0}", new LegitimateDatabase().GetInnermostMessage(ex)) } }; } return new JsonNetResult() { Data = new JsonBaseResult() { Success = true } }; } #endregion } }