public async Task <IActionResult> Index( string form, string path, Dictionary <string, string[]> formData) { var viewModel = formData.ToNormaliseDictionary(string.Empty); var queryParamters = Request.Query; var baseForm = await _schemaFactory.Build(form); if (baseForm == null) { throw new ApplicationException($"Requested form '{form}' could not be found."); } var page = baseForm.GetPage(_pageHelper, path); if (page == null) { throw new ApplicationException($"Requested path '{path}' object could not be found for form '{form}'"); } var sessionGuid = _sessionHelper.GetSessionGuid(); await _bookingService.ProcessMonthRequest(viewModel, baseForm, page, sessionGuid); var routeValuesDictionary = new RouteValueDictionaryBuilder() .WithValue("path", path) .WithValue("form", form) .WithQueryValues(queryParamters) .Build(); return(RedirectToAction("Index", "Home", routeValuesDictionary)); }
public async Task Process(List <IAction> actions, FormSchema formSchema, string formName) { var sessionGuid = _sessionHelper.GetSessionGuid(); var mappingData = await _mappingService.Map(sessionGuid, formName); foreach (var action in actions) { var response = new HttpResponseMessage(); var submitSlug = action.Properties.PageActionSlugs.FirstOrDefault(_ => _.Environment.ToLower().Equals(_environment.EnvironmentName.ToS3EnvPrefix().ToLower())); if (submitSlug == null) { throw new ApplicationException("ValidateService::Process, there is no PageActionSlug defined for this environment"); } var entity = _actionHelper.GenerateUrl(submitSlug.URL, mappingData.FormAnswers); if (!string.IsNullOrEmpty(submitSlug.AuthToken)) { _gateway.ChangeAuthenticationHeader(submitSlug.AuthToken); } response = await _gateway.GetAsync(entity.Url); if (!response.IsSuccessStatusCode) { throw new ApplicationException($"ValidateService::Process, http request to {entity.Url} returned an unsuccessful status code, Response: {JsonConvert.SerializeObject(response)}"); } } }
public async Task <IActionResult> PaymentFailure(string form, [FromQuery] string reference) { var sessionGuid = _sessionHelper.GetSessionGuid(); var data = await _mappingService.Map(sessionGuid, form); var url = await _payService.ProcessPayment(data, form, "payment", reference, sessionGuid); var paymentFailureViewModel = new PaymentFailureViewModel { FormName = form, PageTitle = "Failure", Reference = reference, PaymentUrl = url, StartPageUrl = data.BaseForm.StartPageUrl }; return(View("./Failure", paymentFailureViewModel)); }
public FormAnswers GetFormAnswers() { string sessionGuid = _sessionHelper.GetSessionGuid(); string cachedAnswers = _distributedCache.GetString(sessionGuid); return(cachedAnswers is null ? new FormAnswers { Pages = new List <PageAnswers>() } : JsonConvert.DeserializeObject <FormAnswers>(cachedAnswers)); }
public async Task <string> Submit(string form) { var sessionGuid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(sessionGuid)) { throw new ApplicationException($"A Session GUID was not provided."); } var data = await _mappingService.Map(sessionGuid, form); return(await _submitService.ProcessSubmission(data, form, sessionGuid)); }
public Page GetPageWithMatchingRenderConditions(List <Page> pages) { var guid = _sessionHelper.GetSessionGuid(); var formData = _distributedCache.GetString(guid); var convertedAnswers = !string.IsNullOrEmpty(formData) ? JsonConvert.DeserializeObject <FormAnswers>(formData) : new FormAnswers { Pages = new List <PageAnswers>() }; var answers = convertedAnswers.Pages.SelectMany(_ => _.Answers).ToDictionary(_ => _.QuestionId, _ => _.Response); return(pages.FirstOrDefault(page => page.CheckPageMeetsConditions(answers))); }
public async Task <string> ProcessPaymentResponse(string form, string responseCode, string reference) { var sessionGuid = _sessionHelper.GetSessionGuid(); var mappingEntity = await _mappingService.Map(sessionGuid, form); if (mappingEntity == null) { throw new Exception($"PayService:: No mapping entity found for {form}"); } var currentPage = mappingEntity.BaseForm.GetPage(_pageHelper, mappingEntity.FormAnswers.Path); var paymentInformation = await GetFormPaymentInformation(mappingEntity, form, currentPage); var postUrl = currentPage.GetSubmitFormEndpoint(mappingEntity.FormAnswers, _hostingEnvironment.EnvironmentName.ToS3EnvPrefix()); var paymentProvider = GetFormPaymentProvider(paymentInformation); if (string.IsNullOrWhiteSpace(postUrl.CallbackUrl)) { throw new ArgumentException("PayService::ProcessPaymentResponse, Callback url has not been specified"); } _gateway.ChangeAuthenticationHeader(postUrl.AuthToken); try { paymentProvider.VerifyPaymentResponse(responseCode); await _gateway.PostAsync(postUrl.CallbackUrl, new { CaseReference = reference, PaymentStatus = EPaymentStatus.Success.ToString() }); return(reference); } catch (PaymentDeclinedException) { await _gateway.PostAsync(postUrl.CallbackUrl, new { CaseReference = reference, PaymentStatus = EPaymentStatus.Declined.ToString() }); throw new PaymentDeclinedException("PayService::ProcessPaymentResponse, PaymentProvider declined payment"); } catch (PaymentFailureException) { await _gateway.PostAsync(postUrl.CallbackUrl, new { CaseReference = reference, PaymentStatus = EPaymentStatus.Failure.ToString() }); throw new PaymentFailureException("PayService::ProcessPaymentResponse, PaymentProvider failed payment"); } catch (Exception ex) { _logger.LogError(ex, "The payment callback failed"); throw new Exception(ex.Message); } }
public async Task <string> Submit(string form, string path) { var sessionGuid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(sessionGuid)) { throw new ApplicationException("A Session GUID was not provided."); } var data = await _mappingService.Map(sessionGuid, form); var paymentReference = await _submitService.PaymentSubmission(data, form, sessionGuid); return(await _payService.ProcessPayment(data, form, path, paymentReference, sessionGuid)); }
public async Task Process(List <IAction> actions) { var sessionGuid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(sessionGuid)) { throw new Exception("EmailService::Process: Session has expired"); } var formData = _distributedCache.GetString(sessionGuid); var formAnswers = JsonConvert.DeserializeObject <FormAnswers>(formData); foreach (var action in actions) { await action.Process(_actionHelper, _emailProvider, formAnswers); } }
public Task ProcessTemplatedEmail(List <IAction> actions) { var sessionGuid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(sessionGuid)) { throw new Exception("TemplatedEmailService::Process: Session has expired"); } var formData = _distributedCache.GetString(sessionGuid); var formAnswers = JsonConvert.DeserializeObject <FormAnswers>(formData); foreach (var action in actions) { var templatedEmailProvider = _templatedEmailProviders.Get(action.Properties.EmailTemplateProvider); var convertedAnswers = formAnswers.AllAnswers.ToDictionary(x => x.QuestionId, x => x.Response); var personalisation = new Dictionary <string, dynamic>(); if (action.Properties.IncludeCaseReference) { personalisation.Add("reference", formAnswers.CaseReference); } if (action.Properties.Personalisation is not null && !convertedAnswers.Count.Equals(0)) { action.Properties.Personalisation.ForEach(field => { personalisation.Add(field, convertedAnswers[field]); }); } action.ProcessTemplatedEmail( _actionHelper, templatedEmailProvider, personalisation, formAnswers); } return(null); }
public ValidationResult Validate(Element element, Dictionary <string, dynamic> viewModel, FormSchema baseForm) { if (element.Type != EElementType.MultipleFileUpload) { return new ValidationResult { IsValid = true } } ; var key = $"{element.Properties.QuestionId}{FileUploadConstants.SUFFIX}"; if (!viewModel.ContainsKey(key)) { return new ValidationResult { IsValid = true } } ; List <DocumentModel> documentModel = viewModel[key]; if (documentModel == null) { return new ValidationResult { IsValid = true } } ; var maxCombinedFileSize = element.Properties.MaxCombinedFileSize > 0 ? element.Properties.MaxCombinedFileSize * SystemConstants.OneMBInBinaryBytes : SystemConstants.DefaultMaxCombinedFileSize; var sessionGuid = _sessionHelper.GetSessionGuid(); var cachedAnswers = _distributedCache.GetString(sessionGuid); var convertedAnswers = cachedAnswers == null ? new FormAnswers { Pages = new List <PageAnswers>() } : JsonConvert.DeserializeObject <FormAnswers>(cachedAnswers); var path = viewModel.FirstOrDefault(_ => _.Key.Equals("Path")).Value; var pageAnswersString = convertedAnswers.Pages.FirstOrDefault(_ => _.PageSlug.Equals(path))?.Answers.FirstOrDefault(_ => _.QuestionId == key); var response = new List <FileUploadModel>(); if (pageAnswersString != null) { response = JsonConvert.DeserializeObject <List <FileUploadModel> >(pageAnswersString.Response.ToString()); } if (documentModel.Sum(_ => _.FileSize) + response?.Sum(_ => _.FileSize) < maxCombinedFileSize) { return new ValidationResult { IsValid = true } } ; return(new ValidationResult { IsValid = false, Message = $"The total size of all your added files must not be more than {maxCombinedFileSize.ToReadableMaxFileSize()}MB" }); } } }
public async Task ProcessMonthRequest(Dictionary <string, object> viewModel, string form, string path) { var baseForm = await _schemaFactory.Build(form); if (baseForm is null) { throw new ApplicationException($"Requested form '{form}' could not be found."); } var currentPage = baseForm.GetPage(_pageHelper, path); if (currentPage is null) { throw new ApplicationException($"Requested path '{path}' object could not be found for form '{form}'"); } if (!viewModel.ContainsKey(BookingConstants.BOOKING_MONTH_REQUEST)) { throw new ApplicationException("BookingService::ProcessMonthRequest, request for appointment did not contain requested month"); } var requestedMonth = DateTime.Parse(viewModel[BookingConstants.BOOKING_MONTH_REQUEST].ToString()); var currentDate = DateTime.Now; var bookingElement = (Booking)currentPage.Elements .First(element => element.Type. Equals(EElementType.Booking)); if (requestedMonth.Month.Equals(currentDate.Month) && requestedMonth.Year.Equals(currentDate.Year)) { requestedMonth = currentDate; } if (requestedMonth > new DateTime(currentDate.Year, currentDate.Month, 1).AddMonths(bookingElement.Properties.SearchPeriod)) { throw new ApplicationException("BookingService::ProcessMonthRequest, Invalid request for appointment search, Start date provided is after allowed search period"); } if (requestedMonth < currentDate) { throw new ApplicationException("BookingService::ProcessMonthRequest, Invalid request for appointment search, Start date provided is before today"); } var guid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(guid)) { throw new ApplicationException("BookingService::ProcessMonthRequest Session has expired"); } var cachedAnswers = _distributedCache.GetString(guid); if (cachedAnswers is null) { throw new ApplicationException("BookingService::ProcessMonthRequest, Session data is null"); } var bookingInformationCacheKey = $"{bookingElement.Properties.QuestionId}{BookingConstants.APPOINTMENT_TYPE_SEARCH_RESULTS}"; var convertedAnswers = JsonConvert.DeserializeObject <FormAnswers>(cachedAnswers); var appointmentType = bookingElement.Properties.AppointmentTypes .GetAppointmentTypeForEnvironment(_environment.EnvironmentName); if (appointmentType.NeedsAppointmentIdMapping) { _mappingService.MapAppointmentId(appointmentType, convertedAnswers); } var appointmentTimes = await _bookingProviders.Get(bookingElement.Properties.BookingProvider) .GetAvailability(new AvailabilityRequest { StartDate = requestedMonth.Date, EndDate = requestedMonth.Date.LastDayOfTheMonth(), AppointmentId = appointmentType.AppointmentId, OptionalResources = appointmentType.OptionalResources }); var cachedBookingInformation = JsonConvert.DeserializeObject <BookingInformation>(convertedAnswers.FormData[bookingInformationCacheKey].ToString()); BookingInformation bookingInformation = new() { AppointmentTypeId = appointmentType.AppointmentId, Appointments = appointmentTimes, CurrentSearchedMonth = requestedMonth, FirstAvailableMonth = cachedBookingInformation.FirstAvailableMonth, IsFullDayAppointment = cachedBookingInformation.IsFullDayAppointment, AppointmentEndTime = cachedBookingInformation.AppointmentEndTime, AppointmentStartTime = cachedBookingInformation.AppointmentStartTime }; _pageHelper.SaveFormData(bookingInformationCacheKey, bookingInformation, guid, baseForm.BaseURL); }
public async Task Process(List <IAction> actions, FormSchema formSchema, string formName) { var answers = new List <Answers>(); var sessionGuid = _sessionHelper.GetSessionGuid(); var mappingData = await _mappingService.Map(sessionGuid, formName); foreach (var action in actions) { var response = new HttpResponseMessage(); var submitSlug = action.Properties.PageActionSlugs.FirstOrDefault(_ => _.Environment.ToLower().Equals(_environment.EnvironmentName.ToS3EnvPrefix().ToLower())); if (submitSlug == null) { throw new ApplicationException("RetrieveExternalDataService::Process, there is no PageActionSlug defined for this environment"); } var entity = _actionHelper.GenerateUrl(submitSlug.URL, mappingData.FormAnswers); if (!string.IsNullOrEmpty(submitSlug.AuthToken)) { _gateway.ChangeAuthenticationHeader(submitSlug.AuthToken); } if (entity.IsPost) { response = await _gateway.PostAsync(entity.Url, mappingData.Data); } else { response = await _gateway.GetAsync(entity.Url); } if (!response.IsSuccessStatusCode) { throw new ApplicationException($"RetrieveExternalDataService::Process, http request to {entity.Url} returned an unsuccessful status code, Response: {JsonConvert.SerializeObject(response)}"); } if (response.Content == null) { throw new ApplicationException($"RetrieveExternalDataService::Process, response content from {entity.Url} is null."); } var content = await response.Content.ReadAsStringAsync(); if (string.IsNullOrWhiteSpace(content)) { throw new ApplicationException($"RetrieveExternalDataService::Process, Gateway {entity.Url} responded with empty reference"); } answers.Add(new Answers { QuestionId = action.Properties.TargetQuestionId, Response = JsonConvert.DeserializeObject <string>(content) }); } mappingData.FormAnswers.Pages.FirstOrDefault(_ => _.PageSlug.ToLower().Equals(mappingData.FormAnswers.Path.ToLower())).Answers.AddRange(answers); await _distributedCache.SetStringAsync(sessionGuid, JsonConvert.SerializeObject(mappingData.FormAnswers), CancellationToken.None); }
public ValidationResult Validate(Element element, Dictionary <string, dynamic> viewModel, FormSchema baseForm) { if (!element.Type.Equals(EElementType.MultipleFileUpload)) { return new ValidationResult { IsValid = true } } ; if (element.Properties.Optional && viewModel.ContainsKey(ButtonConstants.SUBMIT)) { return new ValidationResult { IsValid = true } } ; var key = $"{ element.Properties.QuestionId}{FileUploadConstants.SUFFIX}"; var isValid = false; List <DocumentModel> value = viewModel.ContainsKey(key) ? viewModel[key] : null; isValid = !(value is null); if (value is null) { var sessionGuid = _sessionHelper.GetSessionGuid(); var cachedAnswers = _distributedCache.GetString(sessionGuid); var convertedAnswers = cachedAnswers is null ? new FormAnswers { Pages = new List <PageAnswers>() } : JsonConvert.DeserializeObject <FormAnswers>(cachedAnswers); var path = viewModel.FirstOrDefault(_ => _.Key.Equals("Path")).Value; var pageAnswersString = convertedAnswers.Pages.FirstOrDefault(_ => _.PageSlug.Equals(path))?.Answers.FirstOrDefault(_ => _.QuestionId.Equals(key)); var response = new List <FileUploadModel>(); if (pageAnswersString is not null) { response = JsonConvert.DeserializeObject <List <FileUploadModel> >(pageAnswersString.Response.ToString()); if (response.Any()) { isValid = true; } } } return(new ValidationResult { IsValid = isValid, Message = ValidationConstants.FILEUPLOAD_EMPTY }); } } }
public async Task <ProcessPageEntity> ProcessPage(string form, string path, string subPath, IQueryCollection queryParamters) { if (string.IsNullOrEmpty(path)) { _sessionHelper.RemoveSessionGuid(); } var sessionGuid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(sessionGuid)) { sessionGuid = Guid.NewGuid().ToString(); _sessionHelper.SetSessionGuid(sessionGuid); } var baseForm = await _schemaFactory.Build(form); if (baseForm == null) { return(null); } if (!baseForm.IsAvailable(_environment.EnvironmentName)) { throw new ApplicationException($"Form: {form} is not available in this Environment: {_environment.EnvironmentName.ToS3EnvPrefix()}"); } var formData = _distributedCache.GetString(sessionGuid); if (formData == null && path != baseForm.FirstPageSlug && (!baseForm.HasDocumentUpload || path != FileUploadConstants.DOCUMENT_UPLOAD_URL_PATH)) { return new ProcessPageEntity { ShouldRedirect = true, TargetPage = baseForm.FirstPageSlug } } ; if (string.IsNullOrEmpty(path)) { return new ProcessPageEntity { ShouldRedirect = true, TargetPage = baseForm.FirstPageSlug } } ; if (formData != null && path == baseForm.FirstPageSlug) { var convertedFormData = JsonConvert.DeserializeObject <FormAnswers>(formData); if (form.ToLower() != convertedFormData.FormName.ToLower()) { _distributedCache.Remove(sessionGuid); } } var page = baseForm.GetPage(_pageHelper, path); if (page == null) { throw new ApplicationException($"Requested path '{path}' object could not be found for form '{form}'"); } await baseForm.ValidateFormSchema(_pageHelper, form, path); List <object> searchResults = null; if (subPath.Equals(LookUpConstants.Automatic) || subPath.Equals(LookUpConstants.Manual)) { var convertedAnswers = new FormAnswers { Pages = new List <PageAnswers>() }; if (!string.IsNullOrEmpty(formData)) { convertedAnswers = JsonConvert.DeserializeObject <FormAnswers>(formData); } if (convertedAnswers.FormData.ContainsKey($"{path}{LookUpConstants.SearchResultsKeyPostFix}")) { searchResults = ((IEnumerable <object>)convertedAnswers.FormData[$"{path}{LookUpConstants.SearchResultsKeyPostFix}"])?.ToList(); } } if (page.Elements.Any(_ => _.Type == EElementType.PaymentSummary)) { var data = await _mappingService.Map(sessionGuid, form); var paymentAmount = await _payService.GetFormPaymentInformation(data, form, page); page.Elements.First(_ => _.Type == EElementType.PaymentSummary).Properties.Value = paymentAmount.Settings.Amount; } if (page.HasIncomingGetValues) { var convertedAnswers = new FormAnswers { Pages = new List <PageAnswers>() }; if (!string.IsNullOrEmpty(formData)) { convertedAnswers = JsonConvert.DeserializeObject <FormAnswers>(formData); } var result = _incomingDataHelper.AddIncomingFormDataValues(page, queryParamters, convertedAnswers); _pageHelper.SaveNonQuestionAnswers(result, form, path, sessionGuid); } if (page.HasPageActionsGetValues) { await _actionsWorkflow.Process(page.PageActions, null, form); } if (page.Elements.Any(_ => _.Type.Equals(EElementType.Booking))) { var bookingProcessEntity = await _bookingService.Get(baseForm.BaseURL, page, sessionGuid); if (bookingProcessEntity.BookingHasNoAvailableAppointments) { return(new ProcessPageEntity { ShouldRedirect = true, TargetPage = BookingConstants.NO_APPOINTMENT_AVAILABLE }); } searchResults = bookingProcessEntity.BookingInfo; } var viewModel = await GetViewModel(page, baseForm, path, sessionGuid, subPath, searchResults); return(new ProcessPageEntity { ViewModel = viewModel }); }
public async Task <ProcessPageEntity> ProcessPage(string form, string path, string subPath, IQueryCollection queryParameters) { if (string.IsNullOrEmpty(path)) { _sessionHelper.RemoveSessionGuid(); } var sessionGuid = _sessionHelper.GetSessionGuid(); if (string.IsNullOrEmpty(sessionGuid)) { sessionGuid = Guid.NewGuid().ToString(); _sessionHelper.SetSessionGuid(sessionGuid); } var baseForm = await _schemaFactory.Build(form); if (baseForm is null) { return(null); } if (!_formAvailabilityService.IsAvailable(baseForm.EnvironmentAvailabilities, _environment.EnvironmentName)) { _logger.LogWarning($"Form: {form} is not available in this Environment: {_environment.EnvironmentName.ToS3EnvPrefix()}"); return(null); } if (string.IsNullOrEmpty(path)) { return new ProcessPageEntity { ShouldRedirect = true, TargetPage = baseForm.FirstPageSlug } } ; var formData = _distributedCache.GetString(sessionGuid); if (string.IsNullOrEmpty(formData) && !path.Equals(baseForm.FirstPageSlug) && (!baseForm.HasDocumentUpload || !path.Equals(FileUploadConstants.DOCUMENT_UPLOAD_URL_PATH))) { return new ProcessPageEntity { ShouldRedirect = true, TargetPage = baseForm.FirstPageSlug } } ; if (!string.IsNullOrEmpty(formData) && path.Equals(baseForm.FirstPageSlug)) { var convertedFormData = JsonConvert.DeserializeObject <FormAnswers>(formData); if (!form.Equals(convertedFormData.FormName, StringComparison.OrdinalIgnoreCase)) { _distributedCache.Remove(sessionGuid); } } var page = baseForm.GetPage(_pageHelper, path); if (page is null) { throw new ApplicationException($"Requested path '{path}' object could not be found for form '{form}'"); } List <object> searchResults = null; var convertedAnswers = new FormAnswers { Pages = new List <PageAnswers>() }; if (!string.IsNullOrEmpty(formData)) { convertedAnswers = JsonConvert.DeserializeObject <FormAnswers>(formData); } if (page.Elements.Any(_ => _.Type.Equals(EElementType.Summary))) { var journeyPages = baseForm.GetReducedPages(convertedAnswers); foreach (var schemaPage in journeyPages) { await _schemaFactory.TransformPage(schemaPage, convertedAnswers); } } else { await _schemaFactory.TransformPage(page, convertedAnswers); } if (subPath.Equals(LookUpConstants.Automatic) || subPath.Equals(LookUpConstants.Manual)) { if (convertedAnswers.FormData.ContainsKey($"{path}{LookUpConstants.SearchResultsKeyPostFix}")) { searchResults = ((IEnumerable <object>)convertedAnswers.FormData[$"{path}{LookUpConstants.SearchResultsKeyPostFix}"])?.ToList(); } } if (page.HasIncomingGetValues) { var result = _incomingDataHelper.AddIncomingFormDataValues(page, queryParameters, convertedAnswers); _pageHelper.SaveNonQuestionAnswers(result, form, path, sessionGuid); } if (page.HasPageActionsGetValues) { await _actionsWorkflow.Process(page.PageActions, null, form); } if (page.Elements.Any(_ => _.Type.Equals(EElementType.Booking))) { var bookingProcessEntity = await _bookingService.Get(baseForm.BaseURL, page, sessionGuid); if (bookingProcessEntity.BookingHasNoAvailableAppointments) { return(new ProcessPageEntity { ShouldRedirect = true, TargetPage = BookingConstants.NO_APPOINTMENT_AVAILABLE }); } searchResults = bookingProcessEntity.BookingInfo; } var viewModel = await GetViewModel(page, baseForm, path, sessionGuid, subPath, searchResults); return(new ProcessPageEntity { ViewModel = viewModel }); }