public static string GetAccountDocumentCodeName(bool iraAccount, AccountDocumentModel documentModel) { switch (iraAccount) { case true: return(IraDocumentCodeNames[documentModel.AccountDocument]); default: return(NonIraDocumentCodeNames[documentModel.AccountDocument]); } }
private async Task <DialogTurnResult> ParseAllGivenInformationStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var luisResult = (LuisResult)stepContext.Options; var documentModel = new AccountDocumentModel { //get ira or standard account type AccountType = GetEntityModelResolution(luisResult, AccountTypeEntity), //get account document AccountDocument = GetEntityModelResolution(luisResult, DocumentTypeEntity) }; documentModel.SetIsIra(); //determines if account is an IRA acct or Standard //if any account type was specified. if (documentModel.IsIra.HasValue) { stepContext.Values[DocumentModelValue] = documentModel; //the account requested is an IRA if (documentModel.IsIra == 1) { return(await DispatchIraAccountDocumentAsync(stepContext, documentModel, cancellationToken)); } //account is standard return(await DispatchNonIraAccountDocumentAsync(stepContext, documentModel, cancellationToken)); } else { //no account has been supplied //if the document specified is an IRA transfer form, but the user did not specify IRA if (Common.IraOnlyDocumentTypes.Contains(documentModel.AccountDocument)) { documentModel.AccountType = "ira"; stepContext.Values[DocumentModelValue] = documentModel; return(await DispatchIraAccountDocumentAsync(stepContext, documentModel, cancellationToken)); } //otherwise, prompt for which account type. var msg = "Which type of account would you like to see "; if (string.IsNullOrEmpty(documentModel.AccountDocument)) { msg += " documents for?"; } else { msg += $" the {documentModel.AccountDocument} application/form for?"; } msg = ChannelFormattingService.FormatSimpleMessage(stepContext.Context, msg); stepContext.Values[DocumentModelValue] = documentModel; return(await stepContext.PromptAsync($"{nameof(AccountDocumentsDialog)}.accountType", new PromptOptions { Prompt = MessageFactory.Text(msg), RetryPrompt = MessageFactory.Text(ChannelFormattingService.FormatSimpleMessage(stepContext.Context, "Please select a valid account type")), Choices = ChoiceFactory.ToChoices(AccountTypeChoices) }, cancellationToken)); } }
private async Task <DialogTurnResult> DispatchNonIraAccountDocumentAsync(WaterfallStepContext stepContext, AccountDocumentModel documentModel, CancellationToken cancellationToken) { var sendGeneralUrl = false; //if the user requested a Standard acct transfer form. if (Common.IraOnlyDocumentTypes.Contains(documentModel.AccountDocument)) { await stepContext.Context.SendActivityAsync(ChannelFormattingService.FormatSimpleMessage(stepContext.Context, $"Sorry, there is currently not a {documentModel.AccountDocument} document/form for Standard accounts.")); sendGeneralUrl = true; } //the user requested a specific document, find the URL and respond. else if (!string.IsNullOrEmpty(documentModel.AccountDocument)) { var link = ChannelFormattingService.FormatLinkMessageAndSaveToState(stepContext.Context, APIService.GetAccountDocumentURL(documentModel), _botService, cancellationToken); await stepContext.Context.SendActivityAsync(ChannelFormattingService.FormatSimpleMessage(stepContext.Context, $"You can view the Standard {documentModel.AccountDocument} " + $"document by clicking {link}")); } else { sendGeneralUrl = true; } //if the user did not specify a document, or the user requested a standard acct. transfer form, lead them to the general document page. if (sendGeneralUrl) { var link = ChannelFormattingService.FormatLinkMessageAndSaveToState(stepContext.Context, Common.PINonIraDocumentUrl, _botService, cancellationToken); await stepContext.Context.SendActivityAsync(ChannelFormattingService.FormatSimpleMessage(stepContext.Context, $"You can view all Standard Account related documents by clicking {link}. " + $"You can also ask for a specific document in the same fashion and I can direct you right to it.")); } return(await stepContext.NextAsync(null, cancellationToken)); }
private async Task <DialogTurnResult> DispatchIraAccountDocumentAsync(WaterfallStepContext stepContext, AccountDocumentModel documentModel, CancellationToken cancellationToken) { //if no document was specified for the account, lead the user to the general documents page if (string.IsNullOrEmpty(documentModel.AccountDocument)) { var link = ChannelFormattingService.FormatLinkMessageAndSaveToState(stepContext.Context, Common.PIIraDocumentUrl, _botService, cancellationToken); await stepContext.Context.SendActivityAsync(ChannelFormattingService.FormatSimpleMessage(stepContext.Context, $"You can view all Ira-Related Account documents by clicking {link}. " + $"You can also ask for a specific document in the same fashion and I can direct you right to it.")); } //if document was originally specified else { //get the URL and respond. var link = ChannelFormattingService.FormatLinkMessageAndSaveToState(stepContext.Context, APIService.GetAccountDocumentURL(documentModel), _botService, cancellationToken); await stepContext.Context.SendActivityAsync(ChannelFormattingService.FormatSimpleMessage(stepContext.Context, $"You can view the IRA {documentModel.AccountDocument} document by clicking {link}")); } return(await stepContext.NextAsync(null, cancellationToken)); }
public async Task <CreateAccountCommandResponse> Handle(CreateAccountCommand request, CancellationToken cancellationToken) { //try NOTE: Try catch is removed as we have Middleware components (Core.Infrastructure.Middleware) that capture exceptions as they bubble up the application pipeline // For Console apps and tests: exceptions must be captured at the root //{ //========================================================================== // EVENT SOURCING - REFACTORING NOTES //========================================================================= // When migrating to Event Sourcing you will no longer be using Document Client to store the new account // Instead you will create a "AccountCreated" event (events are names in the past tense) // THis event will later be used as part of your aggregate to create an Accout "projection" or "aggregate" // You will also be seperating your Write store from your Read store as this is the //-------------------------------------------------------------------------- //========================================================================= // VALIDATE OUR COMMAND REQUEST USING FLUENT VALIDATION // ValidationExceptions can be captured using Middleware. However it is not as testable or portable outside of the MVC framework // I prefer using manual/granular validation within each command. //========================================================================= CreateAccountValidator validator = new CreateAccountValidator(_mediator); ValidationResult validationResult = validator.Validate(request); if (!validationResult.IsValid) { return(new CreateAccountCommandResponse(validationResult.Errors) { Message = "One or more validation errors occurred." }); } //========================================================================= // CREATE AND STORE OUR DOCUMENT MODEL //========================================================================= // Create the Account Document Model var accountDocumentModel = new AccountDocumentModel(request.Name); accountDocumentModel.Owner.Email = request.Email; accountDocumentModel.Owner.FirstName = request.FirstName; accountDocumentModel.Owner.LastName = request.LastName; // Add the ParitionKey to the document (Moved to document constructor) //accountDocumentModel.DocumentType = Common.Constants.DocumentType.Account(); // Generate collection uri Uri collectionUri = UriFactory.CreateDocumentCollectionUri(_documentContext.Settings.Database, _documentContext.Settings.Collection); ResourceResponse <Document> result; try { // Save the document to document store using the IDocumentContext dependency result = await _documentContext.Client.CreateDocumentAsync( collectionUri, accountDocumentModel ); } catch (Exception ex) { // throw DocumentStoreException (if a custom exception type is desired) // ... Will be caught, logged and handled by the ExceptionHandlerMiddleware // Pass exception up the chain: throw ex; // ...Or pass along as inner exception: //throw new Exception("An error occured trying to use the document store", ex); } finally { // Close any open connections, etc... } if (result.StatusCode == System.Net.HttpStatusCode.Created) { //========================================================================== // SEND EMAIL //========================================================================= // Send an email to the new account owner using the IEmailService dependency var emailMessage = new EmailMessage { ToEmail = request.Email, ToName = String.Concat(request.FirstName, " ", request.LastName), Subject = "Account created", TextContent = String.Concat("Thank you ", String.Concat(request.FirstName, " ", request.LastName), "! your account named ", request.Name, " has been created!"), HtmlContent = String.Concat("Thank you ", String.Concat(request.FirstName, " ", request.LastName), ",<br>Your account named <b>", request.Name, "</b> has been created!") }; try { var emailSent = await _emailService.SendEmail(emailMessage); } catch (Exception ex) { // throw EmailServiceException (if a custom exception type is desired) // ... Will be caught, logged and handled by the ExceptionHandlerMiddleware // Pass the exception up the chain: throw ex; // ...Or pass along as inner exception: //throw new Exception("An error occured trying to use the email service", ex); } finally { // Use alternate communication method... } //========================================================================== // AUTOMAPPER //========================================================================= // Create our domain model using AutoMapper to be returned within our response object. // Add additional mappings into the: Core.Startup.AutoMapperConfiguration class. //var account = AutoMapper.Mapper.Map<Account>(accountDocumentModel); var account = _mapper.Map <Account>(accountDocumentModel); //========================================================================== // POST COMMAND CHECKLIST //========================================================================= // 1. CACHING: Update cache. // 2. SEARCH INDEX: Update Search index or send indexer request. //----------------------------------------------------------------------- return(new CreateAccountCommandResponse { isSuccess = true, Account = account, Message = "Account created." }); } else { return(new CreateAccountCommandResponse { Message = "Could not save model to document store. Status code: " + result.StatusCode }); } }