Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Amazon.CognitoIdentityProvider;
- using Amazon.CognitoIdentityProvider.Model;
- using Enumis.Apply.Api.ServiceInterface.Extensions;
- using Enumis.Apply.Api.ServiceModel;
- using Enumis.Constants;
- using Enumis.Constants.Extensions;
- using Enumis.DataModel.DataTypes;
- using Enumis.DataModel.Extensions;
- using Enumis.DataModel.Indices.GSI.Customer;
- using Enumis.DataModel.Tables;
- using Enumis.DataModel.Validators;
- using Enumis.Interfaces.Applications;
- using Enumis.Interfaces.ChangeTracking;
- using Enumis.Interfaces.Cognito;
- using Enumis.Interfaces.Enums;
- using Enumis.Interfaces.Extensions;
- using Enumis.Interfaces.Processors.Gps;
- using Enumis.Interfaces.Programs;
- using Enumis.Utilities.Api.Types;
- using Enumis.Utilities.Extensions;
- using id3global;
- using Serilog;
- using ServiceStack;
- using ServiceStack.Aws.DynamoDb;
- using ServiceStack.Configuration;
- using ServiceStack.Text;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Net;
- using Address = Enumis.Interfaces.Applications.Address;
- namespace Enumis.Apply.Api.ServiceInterface
- {
- /// <summary>
- /// Defines the <see cref="ApplicationService" />
- /// </summary>
- public class ApplicationService : Service
- {
- #region Properties
- /// <summary>
- /// Gets or sets the AppSettings
- /// </summary>
- public IAppSettings AppSettings { get; set; }
- /// <summary>
- /// Gets or sets the CognitoClient
- /// </summary>
- public AmazonCognitoIdentityProviderClient CognitoClient { get; set; }
- /// <summary>
- /// Gets or sets the CognitoIdentity
- /// </summary>
- public ICognitoIdentity CognitoIdentity { get; set; }
- /// <summary>
- /// Gets or sets the DynamoDb
- /// </summary>
- public IPocoDynamo DynamoDb { get; set; }
- /// <summary>
- /// Gets or sets the Log
- /// </summary>
- public ILogger Log { get; set; }
- /// <summary>
- /// Gets or sets the S3Vault
- /// </summary>
- public S3Vault S3Vault { get; set; }
- #endregion
- #region Methods
- /// <summary>
- /// The Get
- /// </summary>
- /// <param name="request">The <see cref="ApplicationCardDetailRequest" /></param>
- /// <returns>The <see cref="ApplicationCardDetailResponse" /></returns>
- public ApplicationCardDetailResponse Get(ApplicationCardDetailRequest request)
- {
- var application = DynamoDb.GetApplicationByERN(request.ERN).AsIGpsApplication();
- return application?.CardProcessor?.Response == null
- ? new ApplicationCardDetailResponse()
- : application.CardProcessor.Response.ConvertTo<ApplicationCardDetailResponse>();
- }
- /// <summary>
- /// The Get
- /// </summary>
- /// <param name="request">The <see cref="ApplicationsRequest" /></param>
- /// <returns>The <see cref="ApplicationsResponse" /></returns>
- public ApplicationsResponse Get(ApplicationsRequest request)
- {
- var applications = GetGpsApplications().AsApplicationsWeb();
- var applicationsResponse = new ApplicationsResponse
- {
- Applications = applications.Where(x => x.State == ApplicationState.Success).ToList(),
- Application = applications.FirstOrDefault(x => x.State < ApplicationState.Success)
- };
- return applicationsResponse;
- }
- /// <summary>
- /// The Post
- /// </summary>
- /// <param name="request">The <see cref="ApplicationKycRequest" /></param>
- /// <returns>The <see cref="ApplicationKycResponse" /></returns>
- public ApplicationKycResponse Post(ApplicationKycRequest request)
- {
- var authenticateClient =
- new GlobalAuthenticateClient(GlobalAuthenticateClient.EndpointConfiguration
- .wsHttpBinding_GlobalAuthenticate);
- authenticateClient.ClientCredentials.UserName.UserName = "ryan.helms@enumis.co.uk";
- authenticateClient.ClientCredentials.UserName.Password = "40%4MKy4yZdaCKclx1RC";
- var input = new GlobalInputData
- {
- Personal = new GlobalPersonal
- {
- PersonalDetails = request.GetPersonalDetails()
- },
- Addresses = new GlobalAddresses
- {
- CurrentAddress = request.GetCurrentAddress(),
- HistoricAddresses = request.GetHistoricAddresses()
- }
- };
- var profile = new GlobalProfileIDVersion
- {
- ID = new Guid("7c2bcf5a-2fae-456b-995c-450630fb2621"),
- Version = 0
- };
- // Log("||ApplicationKycRequest||", "Profile:", profile.ToJson());
- // Log("||ApplicationKycRequest||", "Input:", input.ToJson());
- var result = authenticateClient.AuthenticateSPAsync(profile, "", input).ConfigureAwait(false).GetAwaiter().GetResult();
- // Log("||ApplicationKycRequest||", "Result:", result.ToJson());
- var response = new ApplicationKycResponse
- {
- Decision = result.BandText,
- Score = result.Score.ToString(),
- AuthenticationId = result.AuthenticationID.ToString(),
- Timestamp = result.Timestamp.ToString(CultureInfo.InvariantCulture)
- };
- // Log("||ApplicationKycRequest||", "Response:", response.ToJson());
- return response;
- }
- /// <summary>
- /// The Get
- /// </summary>
- /// <param name="request">The <see cref="ApplyRegistrationRequest" /></param>
- /// <returns>The <see cref="ApplyRegistrationResponse" /></returns>
- public ApplyRegistrationResponse Post(ApplyRegistrationRequest request)
- {
- try
- {
- var addUserToGroupResult = AddUserToGroup(CognitoIdentity.Username);
- Log.Debug("||ApplicationKycRequest|| Add User To Group Result: {@AddUserToGroupResults}", addUserToGroupResult);
- return new ApplyRegistrationResponse
- {
- AddUserToGroupResponse = addUserToGroupResult
- };
- }
- catch (Exception ex)
- {
- throw new HttpError(HttpStatusCode.BadRequest, ex.Message);
- }
- }
- /// <summary>
- /// The Post
- /// </summary>
- /// <param name="request">The <see cref="AssetUploadRequest" /></param>
- /// <returns>The <see cref="AssetUploadResponse" /></returns>
- public AssetUploadResponse Post(AssetUploadRequest request)
- {
- try
- {
- request.ERN.ThrowIfNullOrEmpty("Application ERN cannot be empty");
- request.Link.ThrowIfNullOrEmpty("Asset file name cannot be empty");
- request.Bytes.ThrowIfNull("Asset Bytes cannot be empty");
- Log.Debug("File Received: {@AssetUploadRequest}", request);
- var originalApplication = DynamoDb.GetApplicationByERN(request.ERN).AsIGpsApplication();
- originalApplication.ThrowIfNull();
- var destinationName = $"{request.Type.ToString().ToLower()}{Path.GetExtension(request.Link)}";
- var destination = $"applications/{originalApplication.CustomerERN}/{originalApplication.ERN}/{destinationName}";
- S3Vault.WriteFile(destination, new MemoryStream(request.Bytes));
- Log.Information("Image Saved: {AssetUploadDestination}", destination);
- request.Bytes = null;
- request.Link = destinationName;
- // Lets upate or add
- var applicationAsset = request.ConvertTo<ApplicationAsset>();
- var existingAsset = originalApplication.Form.Assets.FirstOrDefault(x => x.Type == request.Type && x.Domain == request.Domain);
- if (existingAsset != null)
- {
- applicationAsset.GetChanges(existingAsset).AsModifications().SaveTo(originalApplication);
- originalApplication.Form.Assets.Remove(existingAsset);
- }
- originalApplication.Form.Assets.Add(applicationAsset);
- // Lets move the state of the application
- switch (originalApplication.State)
- {
- case ApplicationState.UploadIdentificationDocuments:
- if (originalApplication.Form.Assets.Any(x => x.Domain == ApplicationAssetDomain.Identification && (int)x.Type < 1000))
- originalApplication.State++;
- break;
- case ApplicationState.UploadAddressDocuments:
- var cutoff = 999;
- if (originalApplication.Form.Assets.Any(x => x.Domain == ApplicationAssetDomain.Identification && x.Type == ApplicationAssetType.DriversLicense)) cutoff = 1000;
- if (originalApplication.Form.Assets.Count(x => x.Domain == ApplicationAssetDomain.Address && (int)x.Type >= cutoff) > 1)
- originalApplication.State++;
- break;
- }
- originalApplication.BumpModifyDate();
- DynamoDb.PutItem(originalApplication.ToDynamoDb());
- return originalApplication.ConvertTo<AssetUploadResponse>();
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, ex.ToString());
- throw new HttpError(HttpStatusCode.BadRequest, ex.Message);
- }
- }
- /// <summary>
- /// The Post
- /// </summary>
- /// <param name="request">The <see cref="ProcessApplicationRequest" /></param>
- /// <returns>The <see cref="ProcessApplicationResponse" /></returns>
- public ProcessApplicationResponse Post(ProcessApplicationRequest request)
- {
- try
- {
- var application = GetApplication(CognitoIdentity.Sub, CognitoIdentity.Email);
- Log.Debug("Returning Application {@application}", application);
- return application.ConvertTo<ProcessApplicationResponse>();
- }
- catch (Exception ex)
- {
- throw new HttpError(HttpStatusCode.BadRequest, ex.Message);
- }
- }
- /// <summary>
- /// The Put
- /// </summary>
- /// <param name="request">The <see cref="ProcessApplicationRequest" /></param>
- /// <returns>The <see cref="ProcessApplicationResponse" /></returns>
- public ProcessApplicationResponse Put(ProcessApplicationRequest request)
- {
- try
- {
- request.ThrowIfNull("Incomming request should not be null");
- Log.Debug("Incomming Request {@ProcessApplicationRequest}", request);
- var application = GetCurrentApplication(request.ConvertTo<GpsApplication>());
- application.ThrowIfNull("Application should not be null");
- Log.Debug("Current Application: {@CurrentApplication}", application);
- var processedApplication = ProcessApplication(application);
- return processedApplication.ConvertTo<ProcessApplicationResponse>();
- }
- catch (Exception ex)
- {
- throw new HttpError(HttpStatusCode.BadRequest, ex.Message);
- }
- }
- /// <summary>
- /// The AddUserToGroup
- /// </summary>
- /// <param name="username">The <see cref="string" /></param>
- /// <returns>The <see cref="AdminAddUserToGroupResponse" /></returns>
- private AdminAddUserToGroupResponse AddUserToGroup(string username)
- {
- return CognitoClient.AdminAddUserToGroupAsync(new AdminAddUserToGroupRequest
- {
- UserPoolId = AppSettings.GetString("COGNITO_USERPOOL_ID"),
- Username = username,
- GroupName = "system:apply"
- }).GetAwaiter().GetResult();
- }
- /// <summary>
- /// The CompleteNewRegistration
- /// </summary>
- /// <param name="application">The <see cref="IApplicationComplete" /></param>
- private void CompleteNewRegistration(IApplicationComplete application)
- {
- if (!application.IsNewRegistration) return;
- var registration = DynamoDb.GetRegistrationByCognitoUserId(CognitoIdentity.Sub);
- var originalRegistration = registration.Clone();
- // TODO: Need to fill these in with valid data
- //AccountCode = "AccountCode".ToNewERN()
- if (!registration.BirthDate.HasValue) registration.BirthDate = DateTime.Parse($"{application.Form.DobYear}-{application.Form.DobMonth}-{application.Form.DobDay}").ToUnixTimeMs();
- if (string.IsNullOrWhiteSpace(registration.Title)) registration.Title = application.Form.Title;
- if (string.IsNullOrWhiteSpace(registration.FirstName)) registration.FirstName = application.Form.FirstName;
- if (string.IsNullOrWhiteSpace(registration.MiddleName)) registration.MiddleName = application.Form.MiddleName;
- if (string.IsNullOrWhiteSpace(registration.LastName)) registration.LastName = application.Form.LastName;
- if (!registration.OriginCountry.HasValue) registration.OriginCountry = Iso.Countries.FindBy(application.Form.Nationality, false)?.IsoCode?.ToInt() ?? 0;
- if (registration.GetChanges(originalRegistration).Any())
- {
- registration.BumpModifyDate();
- DynamoDb.PutItem(registration);
- }
- }
- /// <summary>
- /// The CreateApplication
- /// </summary>
- /// <param name="registration">The <see cref="Registration" /></param>
- /// <returns>The <see cref="IGpsApplication" /></returns>
- private IGpsApplication CreateApplication(Registration registration)
- {
- Log.Debug("Creating new Application for {@Registration}", registration);
- var application = new GpsApplication
- {
- ERN = "Application".ToNewERN(),
- CustomerERN = registration.ERN,
- CreatedDate = DateTime.UtcNow.ToUnixTimeMs(),
- IsNewRegistration = registration.AccountCode.Contains("Accountcode"),
- Form = new Form
- {
- Addresses = new List<Address>
- {
- new Address()
- }
- },
- Program = new Program
- {
- Code = "FLOW",
- Name = "Flow Card"
- }
- };
- var dynamoDb = application.ToDynamoDb();
- DynamoDb.PutItem(dynamoDb);
- Log.Information("Created New Application: {@Application}", application);
- return application;
- }
- /// <summary>
- /// The generateMockCardOffers
- /// </summary>
- /// <returns>The <see cref="List{Offer}"/></returns>
- private List<Offer> generateMockCardOffers()
- {
- var mockOffers = new List<Offer>();
- mockOffers.Add(
- new Offer
- {
- OfferingCode = "XXXXXXXXXXXXX1",
- Costs = new Costs
- {
- ATM = new Rate
- {
- Abroad = new Fee
- {
- Value = 200,
- Type = FeeType.Fixed
- },
- Local = new Fee
- {
- Value = 50,
- Type = FeeType.Fixed
- },
- FxFee = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- },
- Spend = new Rate
- {
- Abroad = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Local = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- FxFee = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- }
- },
- Fees = new Fees
- {
- BankTransfer = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- CreditCard = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- DebitCard = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Dormancy = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Monthly = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- },
- Limits = new Limits
- {
- MaxBalance = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- MaxLoadPerDay = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- MaxSpendPerDay = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- }
- });
- mockOffers.Add(new Offer
- {
- OfferingCode = "XXXXXXXXXXXXX2",
- Costs = new Costs
- {
- ATM = new Rate
- {
- Abroad = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Local = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- FxFee = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- },
- Spend = new Rate
- {
- Abroad = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Local = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- FxFee = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- }
- },
- Fees = new Fees
- {
- BankTransfer = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- CreditCard = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- DebitCard = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Dormancy = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- Monthly = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- },
- Limits = new Limits
- {
- MaxBalance = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- MaxLoadPerDay = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- },
- MaxSpendPerDay = new Fee
- {
- Value = 0,
- Type = FeeType.Fixed
- }
- }
- });
- return mockOffers;
- }
- /// <summary>
- /// The GetApplication
- /// </summary>
- /// <param name="cognitoId">The <see cref="string" /></param>
- /// <param name="cognitoEmail">The <see cref="string" /></param>
- /// <returns>The <see cref="IGpsApplication" /></returns>
- private IGpsApplication GetApplication(string cognitoId, string cognitoEmail)
- {
- var registration = DynamoDb.GetRegistrationByCognitoUserId(cognitoId);
- if (registration == null)
- {
- registration = new Registration
- {
- ERN = "Customer".ToNewERN(),
- Code = GetCustomerCode(),
- CognitoUserId = cognitoId,
- EmailAddress = cognitoEmail,
- CreatedDate = DateTime.UtcNow.ToUnixTimeMs(),
- SecurityQuestions = new List<SecurityQuestion>(),
- RegisteredDate = -1,
- // TODO: Need to fill these in with valid data
- AccountCode = "AccountCode".ToNewERN()
- //BirthDate = DateTime.Parse(context.RawApplication.DOB).ToUnixTimeMs(),
- //Title = context.RawApplication.Title,
- //FirstName = context.RawApplication.FirstName,
- //LastName = context.RawApplication.LastName,
- //AccessCode = context.CreateCardRequest.AccCode,
- //OriginCountry = Countries.FindBy(context.RawApplication.Nationality, false)?.IsoCode?.ToInt() ?? 0
- };
- DynamoDb.PutItem(registration);
- Log.Information("Created New Registration: {@NewRegistration}", registration);
- }
- var applications = GetGpsApplications();
- if (!applications.Any(x => x.State < ApplicationState.Success))
- return CreateApplication(registration);
- var application = applications.FirstOrDefault(x => x.State < ApplicationState.Success);
- application.ThrowIfNull();
- Log.Debug("Found Application: {@Application}", application);
- return application;
- }
- /// <summary>
- /// The GetCurrentApplication
- /// </summary>
- /// <param name="application">The <see cref="IGpsApplication" /></param>
- /// <returns>The <see cref="IGpsApplication" /></returns>
- private IGpsApplication GetCurrentApplication(IGpsApplication application)
- {
- try
- {
- DynamoDb.ThrowIfNull("DynamoDb should not be null");
- var registration = DynamoDb.GetRegistrationByCognitoUserId(CognitoIdentity.Sub);
- registration.ThrowIfNull($"No registration found => {CognitoIdentity.Sub}");
- Log.Debug("Found Registration: {@Registration}", registration);
- var originalApplication = DynamoDb.GetItem<Application>(new DynamoId(registration.ERN, application.ERN)).AsIGpsApplication();
- originalApplication.ThrowIfNull();
- Log.Debug("Found Application: {@Application}", originalApplication);
- // lets normailzie / humanize the data
- application.Form.ToTitleCase2All();
- application.Form.Addresses.ForEach(x => x.ToTitleCase2All());
- application.Form.GetChanges(originalApplication.Form).AsModifications().SaveTo(originalApplication);
- // Lets merge in just the form
- originalApplication.Form.MergeWith(application.Form);
- return originalApplication;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, nameof(GetCurrentApplication));
- throw new HttpError(HttpStatusCode.BadRequest, ex.Message);
- }
- }
- /// <summary>
- /// The GetCustomerCode
- /// </summary>
- /// <returns>The <see cref="string" /></returns>
- private string GetCustomerCode()
- {
- string customerCode;
- bool exists;
- do
- {
- Log.Verbose("Generating Customer Code");
- customerCode = RandomExtensions.AlphaNumeric(10);
- var code = customerCode;
- exists = DynamoDb.Query(DynamoDb.FromQueryIndex<CodeGlobalIndex>(x => x.Code == code)).Any();
- } while (exists);
- Log.Information("Generated Customer Code: {CustomerCode}", customerCode);
- return customerCode;
- }
- /// <summary>
- /// The GetGpsApplications
- /// </summary>
- /// <returns>The <see cref="List{IGpsApplication}" /></returns>
- private List<IGpsApplication> GetGpsApplications()
- {
- DynamoDb.ThrowIfNull("DynamoDb should not be null");
- var registration = DynamoDb.GetRegistrationByCognitoUserId(CognitoIdentity.Sub);
- if (registration == null) return new List<IGpsApplication>();
- Log.Verbose("Looking for Existing Applications: {CustomerERN}", registration.ERN);
- var applications = DynamoDb.FromQuery<Application>(x => x.CustomerERN == registration.ERN)
- .Exec()
- .Select(x => x.AsIGpsApplication())
- .ToList();
- return applications;
- }
- /// <summary>
- /// The ProcessApplication
- /// </summary>
- /// <param name="application">The <see cref="IGpsApplication" /></param>
- /// <returns>The <see cref="IGpsApplication" /></returns>
- private IGpsApplication ProcessApplication(IGpsApplication application)
- {
- switch (application.State)
- {
- case ApplicationState.NewApplication:
- ValidateApplicationForm(application);
- CompleteNewRegistration(application);
- // TODO: This is a temp try/catch to ensure we continue while KYC is in progress.
- try
- {
- var results = Post(application.Form.ConvertTo<ApplicationKycRequest>());
- }
- catch (Exception e)
- {
- Log.Error(e, e.Message);
- }
- //TODO: how de we interpert / process these results
- application.State++;
- break;
- case ApplicationState.UploadIdentificationDocuments:
- application.State++;
- break;
- case ApplicationState.UploadAddressDocuments:
- application.State++;
- // Lets mock some card offer data
- application.CardOffers = generateMockCardOffers();
- break;
- case ApplicationState.AcceptProductOffering:
- application.State++;
- break;
- case ApplicationState.Processing:
- application.State++;
- break;
- case ApplicationState.Pending:
- application.State++;
- break;
- case ApplicationState.Success:
- application.State = ApplicationState.NewApplication;
- break;
- case ApplicationState.Failure:
- application.State++;
- break;
- default:
- throw new HttpError(HttpStatusCode.BadRequest, "Applciation State is invlaid");
- }
- application.BumpModifyDate();
- DynamoDb.PutItem(application.ToDynamoDb());
- return application;
- }
- /// <summary>
- /// The ValidateApplicationForm
- /// </summary>
- /// <param name="application">The <see cref="IHasForm" /></param>
- private void ValidateApplicationForm(IHasForm application)
- {
- var newApplicationFormValidator = new NewApplicationFormValidator();
- var validationResults = newApplicationFormValidator.Validate(application.Form);
- if (!validationResults.IsValid) throw new HttpError(HttpStatusCode.BadRequest, string.Join(Environment.NewLine, validationResults.Errors.Select(x => x.ErrorMessage)));
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement