This commit is contained in:
Zeeshaun
2026-03-13 09:28:55 -05:00
parent a675c5f5b0
commit 4e6099ff5c
184 changed files with 13756 additions and 0 deletions
@@ -0,0 +1,17 @@
**/*.bat
**/*.log
**/*.md
**/*.yml
**/.dockerignore
**/.editorconfig
**/.git
**/.gitattributes
**/.gitignore
**/.vs
**/.vscode
**/bin
**/dist
**/dockerfile
**/node_modules
**/obj
**/package-lock.json
+369
View File
@@ -0,0 +1,369 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
+39
View File
@@ -0,0 +1,39 @@
# .NET Core SDK
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS aspnetcore-build
# Copy Projects
COPY LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj ./source/LCU.Api.Internal.DataCleanUp/
COPY LCU.Library.Internal.DataCleanUpModel/LCU.Library.Internal.DataCleanUpModel.csproj ./source/LCU.Library.Internal.DataCleanUpModel/
# Install Credential Provider and set env variables to enable Nuget restore with auth
ARG PAT=bh2lq3jibktw67b2wdbqyfln7cd3je6lk52kijntpj43v6kimpgq
RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | sh
#RUN wget -qO- https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | bash
ENV NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED true
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS "{\"endpointCredentials\": [{\"endpoint\":\"https://landmarkcu.pkgs.visualstudio.com/_packaging/LCU-Internal/nuget/v3/index.json\", \"password\":\"${PAT}\"}]}"
# .NET Core Restore, use auth'd feed
RUN dotnet restore -s "https://landmarkcu.pkgs.visualstudio.com/_packaging/LCU-Internal/nuget/v3/index.json" -s "https://api.nuget.org/v3/index.json" ./source/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj
# Copy All Files
COPY . ./source/
FROM aspnetcore-build AS test
LABEL test=true
COPY LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj ./source/LCU.Api.Internal.DataCleanUpTest/
RUN dotnet restore ./source/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj
RUN dotnet test -c Release --results-directory /testresults --logger "trx;LogFileName=test_results.trx" ./source/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj
# .NET Core Publish
FROM aspnetcore-build as publish
RUN dotnet publish ./source/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj -c Release -o /dist
# ASP.NET Core
FROM mcr.microsoft.com/dotnet/aspnet:8.0
#RUN apk add --no-cache icu-libs
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENV ASPNETCORE_ENVIRONMENT=Development
WORKDIR /app
COPY --from=publish /dist .
ENTRYPOINT ["dotnet", "LCU.Api.Internal.DataCleanUp.dll"]
@@ -0,0 +1,43 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.DataCleanUp", "LCU.Api.Internal.DataCleanUp\LCU.Api.Internal.DataCleanUp.csproj", "{F99AB4C0-B967-4368-A313-9751428D403E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Library.Internal.DataCleanUpModel", "LCU.Library.Internal.DataCleanUpModel\LCU.Library.Internal.DataCleanUpModel.csproj", "{264F8A9D-6544-4D36-ACE5-04B0DF457DF6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.DataCleanUpTest", "LCU.Api.Internal.DataCleanUpTest\LCU.Api.Internal.DataCleanUpTest.csproj", "{BAC900C2-55C7-4DA5-949E-2A5923C9CF37}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LCU.Api.Internal.DataCleanUpLib", "LCU.Api.Internal.DataCleanUpLib\LCU.Api.Internal.DataCleanUpLib.csproj", "{2CA97F85-1B3D-45C7-9FD8-A3613220F566}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F99AB4C0-B967-4368-A313-9751428D403E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F99AB4C0-B967-4368-A313-9751428D403E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F99AB4C0-B967-4368-A313-9751428D403E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F99AB4C0-B967-4368-A313-9751428D403E}.Release|Any CPU.Build.0 = Release|Any CPU
{264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Release|Any CPU.Build.0 = Release|Any CPU
{BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Release|Any CPU.Build.0 = Release|Any CPU
{2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8BCD4B79-66E0-4EEE-880A-D70808A224D1}
EndGlobalSection
EndGlobal
@@ -0,0 +1,44 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class CoreApiWrapperConfiguration
{
public int CoreApiTimeout { get; set; }
public int RetryGetAccessChannelPersonIncludes { get; set; }
public string CoreApiWrapperUrl { get; set; }
public string GetAgreePersonsWithHyphenatedUserId { get; set; }
public string GetActiveCustodialAgreePersonNumbers { get; set; }
public string GetActiveCustodialVruCardAgreementAgreePersons { get; set; }
public string GetVipSavingsToFund { get; set; }
public string GetAdminBranchCodeChangeAccountNumbers { get; set; }
public string GetAccountsForGroupAnalysis { get; set; }
public string GetPersonsForAtmCheckHolds { get; set; }
public string AccessChannelPersons { get; set; }
public string AccessType { get; set; }
public string AccesschannelPersonWithIncludes { get; set; }
public string GetAccountsByMajorMinorBranchAndStatus { get; set; }
public string PutPersonAgreementDetailTypes { get; set; }
public string GetTransactionExternalDescriptionsWithSsn { get; set; }
public string PutTransactionExternalDescription { get; set; }
public string PostFundsToAccount { get; set; }
public string PutAccountBranchCode { get; set; }
public string PutAccountLoanToValue { get; set; }
public string PutAccountAnalysisGroup { get; set; }
public string PutPersonUserFieldForAtmCheckHolds { get; set; }
public string PostPersonUserFieldForAtmCheckHolds { get; set; }
public string PostPersonAccount { get; set; }
public string PostOrganizationAccount { get; set; }
public string PutOrganizationMaintenanceRequest { get; set; }
public string PutAccountNickNameUpdateRequest { get; set; }
public string GetAgreementByUserId { get; set; }
public string GetPersonPostalAddressByPersonNumber { get; set; }
public string PutAddrLineByPersonNumber { get; set; }
public string PutAccountCreditReportType { get; set; }
public string GetPropertyNumberByAccountNumber { get; set; }
public string GetAccountByAccountNumber { get; set; }
public string PutPersonUserField { get; set; }
public string PropertyUserField { get; set; }
public string PostPropertyUserField { get; set; }
public string PutPropertyUserField { get; set; }
public string PersonUserField { get; set; }
public string AccountUserField { get; set; }
}
@@ -0,0 +1,11 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class DataCleanUpConfiguration
{
public string AppName { get; set; }
public string SeqUrl { get; set; }
public string TimeZone { get; set; }
public string SeqApiKey { get; set; }
public string[] CorsAllowedOrigins { get; set; }
public FeatureFlags FeatureFlags { get; set; }
}
@@ -0,0 +1,17 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class DataCleanupDefaults
{
public string DigitalBankingBranchCode { get; set; }
public string MemberCheckHoldsUserFieldCode { get; set; }
public int MemberCheckHoldsDays { get; set; }
public List<string> LtvExcludedMinorAccountTypes { get; set; }
public string BatchAddFunds { get; set; }
public string BatchAddFundsSummarySourcePath { get; set; }
public string BatchSavingsSourcePath { get; set; }
public string BatchSavingsSummarySourcePath { get; set; }
public string AccountNicknameSourcePath { get; set; }
public string PmiCancelSourcePath { get; set; }
public string PmiCancelSummaryPath { get; set; }
}
@@ -0,0 +1,35 @@
using System.Reflection;
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class EnvironmentView : IEnvironmentView
{
public string Application => _env.ApplicationName;
public DateTime CurrentDate => DateTime.Now;
public string BuildVersion => AssembleBuildVersion();
public DateTime BuildDate => AssemblyBuildDate();
public string Environment => _env.EnvironmentName;
private readonly IWebHostEnvironment _env;
public EnvironmentView(IWebHostEnvironment env)
{
_env = env;
}
public static DateTime AssemblyBuildDate()
{
//https://stackoverflow.com/a/804310/266594
Assembly assembly = Assembly.GetExecutingAssembly();
FileInfo fileInfo = new FileInfo(assembly.Location);
DateTime lastModified = fileInfo.LastWriteTime;
return lastModified;
}
public static string AssembleBuildVersion()
{
var version = Assembly.GetExecutingAssembly().GetName().Version;
return version == null ? "-.-.-" : version.ToString(); ;
}
}
@@ -0,0 +1,12 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class FannieMaeConfiguration
{
public string PersonNumberLabel { get; set; }
public string ErrorFileDefaultName { get; set; }
public string SummaryEmailSubject { get; set; }
public string FileDateFormat { get; set; }
public string DnaDateFormat { get; set; }
public string PoolDateUserFieldId { get; set; }
public string PoolNbrUserFieldId { get; set; }
}
@@ -0,0 +1,5 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class FeatureFlags
{
public bool RunDataCleanUpConsumer { get; set; }
}
@@ -0,0 +1,9 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class FileOperationsConfiguration
{
public string FileOperationsUrl { get; set; }
public string GetFile { get; set; }
public string WriteFile { get; set; }
public string BuildDynamicFileList { get; set; }
}
@@ -0,0 +1,9 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class FundingCoreRequests
{
public List<string> MajorAccountTypes { get; set; }
public List<string> MinorAccountTypes { get; set; }
public List<string> AccountStatusTypes { get; set; }
public List<long> BranchCodeTypes { get; set; }
}
@@ -0,0 +1,10 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class FundsDefaults
{
public string ClearingCategoryCode { get; set; }
public double FundAmount { get; set; }
public string FundTypeCode { get; set; }
public string FundTypeDetailCode { get; set; }
}
@@ -0,0 +1,12 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class FundsToAccountDefaults
{
public string Description { get; set; }
public double TransactionAmount { get; set; }
public string TransactionTypeCode { get; set; }
public string GLAccountNumber { get; set; }
public string TransactionTypeCodeGL { get; set; }
public string TransactionTypeCodeDeposit { get; set; }
public FundsDefaults FundsDefaults { get; set; }
}
@@ -0,0 +1,10 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public interface IEnvironmentView
{
string Application { get; }
DateTime CurrentDate { get; }
string BuildVersion { get; }
DateTime BuildDate { get; }
string Environment { get; }
}
@@ -0,0 +1,8 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class IndirectSavingsRequirementsDefaults : FundsToAccountDefaults
{
public FundingCoreRequests FundingCoreRequests { get; set; }
}
@@ -0,0 +1,15 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class NcoaConfiguration
{
public string PrimaryAddressLabel { get; set; }
public string StreetTypeLabel { get; set; }
public string UsaLabel { get; set; }
public string UrlBase { get; set; }
public string PersonNumberLabel { get; set; }
public string PoBoxLabel { get; set; }
public string PoBoxAddressTypeLabel { get; set; }
public string ErrorFileDefaultName { get; set; }
public string SummaryEmailSubject { get; set; }
public char ExclusionListDelimiter { get; set; }
}
@@ -0,0 +1,6 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class NotificationsApiConfiguration
{
public string EmailEndpoint { get; set; }
}
@@ -0,0 +1,16 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class SavingsDefaults
{
public string BatchAccountDescription { get; set; }
public string AccountDescription { get; set; }
public string BankOrganizationNumber { get; set; }
public string CurrentMinorAccountTypeCode { get; set; }
public string DeliveryMethodCode { get; set; }
public string MajorAccountTypeCode { get; set; }
public string OwnershipCode { get; set; }
public bool IsTaxReportedForSigner { get; set; }
public bool IsTaxReportedForOwner { get; set; }
public bool IsValid { get; set; }
public string CurrentAccountStatusCode { get; set; }
}
@@ -0,0 +1,7 @@
namespace LCU.Api.Internal.DataCleanUp.Configuration;
public class SavingsMissingRequirementsDefaults
{
public SavingsDefaults SavingDefaults { get; set; }
public FundsToAccountDefaults FundsToAccountDefaults { get; set; }
}
@@ -0,0 +1,34 @@
using Serilog;
using MassTransit;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Services;
using LCU.Library.Internal.Exceptions;
namespace LCU.Api.Internal.DataCleanUp.Consumers;
public class DataCleanUpConsumer : IConsumer<DataCleanUpRequest>
{
private readonly IServiceScopeFactory _scopeFactory;
public DataCleanUpConsumer(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public async Task Consume(ConsumeContext<DataCleanUpRequest> context)
{
try
{
using var scope = _scopeFactory.CreateScope();
await Task.Run(() => scope.ServiceProvider.GetRequiredService<IDataCleanUpService>().DetermineCleanUp(context.Message));
}
catch (ServiceException)
{
throw;
}
catch (Exception exception)
{
Log.Fatal(exception, $"Unexpected Failure");
throw;
}
}
}
@@ -0,0 +1,392 @@
using Microsoft.AspNetCore.Mvc;
using Serilog;
using LCU.Api.Internal.DataCleanUp.Services;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.DataCleanUpModel.Enum;
using LCU.Library.Internal.ApiResponse.Models;
namespace LCU.Api.Internal.DataCleanUp.Controllers;
[ApiController]
[Route("[controller]")]
public class QueueDataCleanUpController : ControllerBase
{
private readonly IQueueDataCleanUpService _queueDataCleanUpService;
public QueueDataCleanUpController(IQueueDataCleanUpService queueDataCleanUpService)
{
_queueDataCleanUpService = queueDataCleanUpService;
}
[HttpPost("QueueDataCleanUp")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueDataCleanUp([FromBody] DataCleanUpRequest request)
{
try
{
_queueDataCleanUpService.QueueDataCleanUp(request);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueHyphenatedUserIdCleanUp")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueHyphenatedUserIdCleanUp()
{
try
{
_queueDataCleanUpService.QueueHyphenatedUserIdCleanUp();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueAccountNickname")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueAccountNicknameAsync()
{
try
{
await _queueDataCleanUpService.QueueUpdateAccountNickname();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueuePmiCancel")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueuePmiCancelAccountUpdateAsync()
{
try
{
await _queueDataCleanUpService.QueuePmiCancelUpdate();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueDeactivateCustodialEAgreements")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueDeactivateCustodialEAgreements()
{
try
{
_queueDataCleanUpService.QueueDeactivateCustodialEAgreements();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueCloseCustodialVruAgreements")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueCloseCustodialVruAgreements()
{
try
{
_queueDataCleanUpService.QueueCloseCustodialVruAgreements();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueMaskTransactionExternalDescriptionWithSsn")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueMaskTransactionExternalDescriptionWithSsn()
{
try
{
_queueDataCleanUpService.QueueMaskTransactionExternalDescriptionWithSsn();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueAddFundsToVipSavingsAccounts")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueAddFundsToVipSavingsAccounts()
{
try
{
_queueDataCleanUpService.QueueAddFundsToVipSavingsAccounts();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueBatchAddFundsToVipSavingsAccounts")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueBatchAddFundsToVipSavingsAccounts()
{
try
{
_queueDataCleanUpService.QueueBatchAddFundsToVipSavingsAccounts();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdateAdminBranchCodesByAccountNumber")]
public IActionResult QueueUpdateAdminBranchCodesByAccountNumber()
{
try
{
_queueDataCleanUpService.QueueUpdateAdminBranchCodesByAccountNumber();
return Ok();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdateAccountLoanToValue")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueUpdateAccountLoanToValue()
{
try
{
_queueDataCleanUpService.QueueUpdateAccountLoanToValue();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdateAccountGroupForAnalysis")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueUpdateAccountGroupForAnalysis()
{
try
{
_queueDataCleanUpService.QueueUpdateAccountGroupForAnalysis();
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdatePersonForCheckHolds")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueUpdatePersonForCheckHolds([FromBody] UpdatePersonForCheckHoldRequest request)
{
try
{
await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdatePersonForCheckHolds);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdateNcoaProcess")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueUpdateNcoaProcess([FromBody] NcoaUpdateRequest request)
{
try
{
await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdateNcoaProcess);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdateAccountCreditReportType")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public IActionResult QueueUpdateAccountCreditReportType([FromBody] CreditReportTypeRequest request)
{
try
{
_queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdateAccountCreditReportType);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueUpdateFannieMaeMortgage")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueUpdateFannieMaeMortgage([FromBody] FannieMaeMortgageRequest request)
{
try
{
await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdateFannieMaeMortgage);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("QueueIndirectFunding")]
[ProducesResponseType(202)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<IActionResult> QueueIndirectFunding([FromBody] IndirectFundingRequest request)
{
try
{
await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.AddFundsToIndirectSavingsAccounts);
return Accepted();
}
catch (ServiceException exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
}
catch (Exception exception)
{
Log.Error(exception, "Unexpected Exception");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
@@ -0,0 +1,33 @@
using LCU.Api.Internal.DataCleanUp.Configuration;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace LCU.Api.Internal.DataCleanUp.Controllers;
[Route("api/[controller]")]
[ApiController]
public class StatusController : ControllerBase
{
private readonly IEnvironmentView _environmentView;
public StatusController(IEnvironmentView environmentView)
{
_environmentView = environmentView;
}
[HttpGet]
[ProducesResponseType(200)]
[ProducesResponseType(500)]
public IActionResult Get()
{
try
{
Log.Verbose($"{_environmentView.Application}");
return Ok(_environmentView);
}
catch (Exception ex)
{
Log.Error(ex, "Failure to return status");
return StatusCode((int)System.Net.HttpStatusCode.InternalServerError);
}
}
}
@@ -0,0 +1,365 @@
using System.Net;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Library.Internal.ApiSecurity.Models;
using LCU.Library.Internal.ApiSecurity.Enums;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
using LCU.Library.Internal.LcuHttpClient.HttpRequest;
using LCU.Library.Internal.LcuHttpClient.Utilities;
namespace LCU.Api.Internal.DataCleanUp.DataAccess;
public class CoreApiWrapperDao : ICoreApiWrapperDao
{
private readonly ApiSecurityConfiguration _apiSecurityConfiguration;
private readonly CoreApiWrapperConfiguration _coreApiWrapperConfiguration;
private readonly IPostRequest _postRequest;
private readonly IPutRequest _putRequest;
private readonly IGetRequest _getRequest;
private const string ClientKeyValue = "DataCleanUp";
private const string UpdateKeyParameterKey = "updateKey";
private const string IncludesParameterKey = "includes";
private const string AccountNoParameterKey = "accountNumber";
private const string PersonNumberParameterKey = "personNumber";
private const string PropertyNumberParameterKey = "propertyNumber";
public CoreApiWrapperDao(
ApiSecurityConfiguration apiSecurityConfiguration,
CoreApiWrapperConfiguration coreApiWrapperConfiguration,
IPostRequest postRequest,
IPutRequest putRequest,
IGetRequest getRequest
)
{
_apiSecurityConfiguration = apiSecurityConfiguration;
_coreApiWrapperConfiguration = coreApiWrapperConfiguration;
_postRequest = postRequest;
_putRequest = putRequest;
_getRequest = getRequest;
}
public async Task<IEnumerable<AgreePerson>> GetAgreePersonsWithHyphenatedUserIds()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAgreePersonsWithHyphenatedUserId}";
var response = await _getRequest.Async<IEnumerable<AgreePerson>>(path, 0);
return response;
}
public async Task<IEnumerable<string>> GetActiveCustodialAgreePersonNumbers()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetActiveCustodialAgreePersonNumbers}";
var response = await _getRequest.Async<IEnumerable<string>>(path, 0);
return response;
}
public async Task<IEnumerable<AgreePerson>> GetActiveCustodialVruCardAgreementAgreePersons()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetActiveCustodialVruCardAgreementAgreePersons}";
return await _getRequest.Async<IEnumerable<AgreePerson>>(path, 0);
}
public async Task<IEnumerable<string>> GetVipSavingsToFund()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetVipSavingsToFund}";
return await _getRequest.Async<IEnumerable<string>>(path, 0);
}
public async Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request
)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessChannelPersons}";
return await _getRequest.Async<CoreApiMessage<IEnumerable<AccessChannelPerson>>>(HttpUtilities.BuildEndPointWithQueryParams(path, request), 0);
}
public async Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request,
List<string> includes
)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccesschannelPersonWithIncludes}";
var dictionaryOfParameters = HttpUtilities.BuildDictionaryValues(request);
foreach (var includedString in includes)
{
dictionaryOfParameters.Add(IncludesParameterKey, includedString);
}
return await _getRequest.AsyncWithNewton<CoreApiMessage<IEnumerable<AccessChannelPerson>>>(HttpUtilities.BuildEndPointWithQueryParams(path, dictionaryOfParameters),
null, _coreApiWrapperConfiguration.RetryGetAccessChannelPersonIncludes);
}
public async Task<IEnumerable<ExternalDescription>> GetTransactionsExternalDescriptionsWithSsn()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetTransactionExternalDescriptionsWithSsn}";
return await _getRequest.Async<IEnumerable<ExternalDescription>>(path, 0);
}
public async Task<IEnumerable<string>> GetBranchCodeChangeAccountNumbers()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAdminBranchCodeChangeAccountNumbers}";
return await _getRequest.Async<IEnumerable<string>>(path, 0);
}
public async Task<Agreement> GetAgreementByUserId(string userId)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAgreementByUserId}";
var finalPath = path.Replace("{userId}", userId);
return await _getRequest.Async<Agreement>(finalPath, 0);
}
public async Task<IReadOnlyCollection<PersonPostalAddress>> GetPersonPostalAddressByPersonNumber(int personNumber)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetPersonPostalAddressByPersonNumber}?personNumber={personNumber}";
var coreMessage = await _getRequest.AsyncWithNewton<CoreApiMessage<IReadOnlyCollection<PersonPostalAddress>>>(path);
return coreMessage.MessageBody;
}
public async Task<IEnumerable<string>> GetGroupUpdateForAnalysisAccountNumbers()
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountsForGroupAnalysis}";
return await _getRequest.Async<IEnumerable<string>>(path, 0);
}
public async Task<IEnumerable<PersonCheckHoldsUserField>> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetPersonsForAtmCheckHolds}"
+ $"?currentDate={resetStartDate}&checkholdEndDate={resetEndDate}&fetchSize={fetchSize}";
return await _getRequest.Async<IEnumerable<PersonCheckHoldsUserField>>(path, 0, _coreApiWrapperConfiguration.CoreApiTimeout);
}
public async Task<IEnumerable<Property>> GetPropertyNumberByAccountNumber(long accountNumber)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetPropertyNumberByAccountNumber}"
+ $"?{AccountNoParameterKey}={accountNumber}";
return await _getRequest.Async<IEnumerable<Property>>(path, 0);
}
public async Task<Account> GetAccountByAccountNumber(long accountNumber)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountByAccountNumber}"
+ $"?{AccountNoParameterKey}={accountNumber}";
return await _getRequest.Async<Account>(path, 0);
}
public async Task<IEnumerable<PropertyUserField>> GetPropertyUserField(long propertyNumber)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PropertyUserField}?{PropertyNumberParameterKey}={propertyNumber}";
var message = await _getRequest.AsyncWithNewton<CoreApiMessage<IEnumerable<PropertyUserField>>>(path);
return message.MessageBody;
}
public async Task<IEnumerable<AccountUserField>> GetAccountUserField(long accountNumber)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccountUserField}?{AccountNoParameterKey}={accountNumber}";
var message = await _getRequest.AsyncWithNewton<CoreApiMessage<IEnumerable<AccountUserField>>>(path);
return message.MessageBody;
}
public async Task<IEnumerable<AccountsByMajorMinorBranchAndStatusResponse>> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request)
{
var httpStatusCodes = new List<HttpStatusCode>() { HttpStatusCode.NoContent };
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountsByMajorMinorBranchAndStatus}";
return await _getRequest.Async<IEnumerable<AccountsByMajorMinorBranchAndStatusResponse>> (HttpUtilities.BuildEndPointWithKeyValuePairs(path, request), httpStatusCodes);
}
public async Task<PersonAddrLine> UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAddrLineByPersonNumber}";
var uri = new Uri(path);
var response = await _putRequest.Async<PersonAddrLine, PersonAddrLine>(uri, ncoaRequest, HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
return response;
}
public async Task<AccessChannelPerson> UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessChannelPersons}?{UpdateKeyParameterKey}={updateKey}";
var uri = new Uri(path);
var response = await _putRequest.Async<AccessChannelPerson, AccessChannelPerson>(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
return response;
}
public async Task<AccessType> UpdateAccessType(AccessTypeUpdateRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessType}";
var uri = new Uri(path);
var response = await _putRequest.Async<AccessTypeUpdateRequest, AccessType>(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
return response;
}
public async Task<BasicResponse> UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPersonAgreementDetailTypes}";
var uri = new Uri(path);
return await _putRequest.Async<PersonAgreementDetailTypeRequest, BasicResponse>(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> UpdateTransactionsExternalDescriptions(ExternalDescription request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutTransactionExternalDescription}";
var uri = new Uri(path);
return await _putRequest.Async<ExternalDescription, BasicResponse>(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<List<BasicResponse>> PostFundsToAccount(List<FundsToAccountRequest> requests)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostFundsToAccount}";
var uri = new Uri(path);
return await _postRequest.Async<List<FundsToAccountRequest>, List<BasicResponse>>(uri, requests,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> UpdateBranchCodesForAccountNumbers(AccountBranchUpdateRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountBranchCode}";
var uri = new Uri(path);
return await _putRequest.Async<AccountBranchUpdateRequest, BasicResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> UpdateAccountLoanToValue(AccountLtvUpdateRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountLoanToValue}";
var uri = new Uri(path);
var result = await _putRequest.Async<AccountLtvUpdateRequest, BasicResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
return result;
}
public async Task<BasicResponse> UpdateAccountGroupForAnalysis(AccountAnalysisGroupMaintenanceRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountAnalysisGroup}";
var uri = new Uri(path);
return await _putRequest.Async<AccountAnalysisGroupMaintenanceRequest, BasicResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<PersonUserField> UpdateAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPersonUserFieldForAtmCheckHolds}";
var uri = new Uri(path);
return await _putRequest.Async<PersonUserFieldRequest, PersonUserField>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<PersonUserField> AddAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostPersonUserFieldForAtmCheckHolds}";
var uri = new Uri(path);
return await _postRequest.Async<PersonUserFieldRequest, PersonUserField>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<CreatedAccountResponse> PostOrganizationAccount(CreateOrganizationAccountRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostOrganizationAccount}";
var uri = new Uri(path);
return await _postRequest.Async<CreateOrganizationAccountRequest, CreatedAccountResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<CreatedAccountResponse> PostPersonAccount(CreatePersonAccountRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostPersonAccount}";
var uri = new Uri(path);
return await _postRequest.Async<CreatePersonAccountRequest, CreatedAccountResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> PutOrganizationMaintenanceRequest(OrganizationMaintenanceRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutOrganizationMaintenanceRequest}";
var uri = new Uri(path);
return await _putRequest.Async<OrganizationMaintenanceRequest, BasicResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> PutAccountNicknameUpdateRequest(AccountNickNameUpdateRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountNickNameUpdateRequest}";
var uri = new Uri(path);
return await _putRequest.Async<AccountNickNameUpdateRequest, BasicResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> UpdateAccountCreditReportType(AccountCreditReportTypeUpdateRequest request)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountCreditReportType}";
var uri = new Uri(path);
return await _putRequest.Async<AccountCreditReportTypeUpdateRequest, BasicResponse>(uri, request,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> PutPersonUserField(PersonUserField personUserField)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPersonUserField}";
var uri = new Uri(path);
return await _putRequest.Async<PersonUserField, BasicResponse>(uri, personUserField,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> PostPropertyUserField(PropertyUserField propertyUserField)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostPropertyUserField}";
var uri = new Uri(path);
return await _postRequest.Async<PropertyUserField, BasicResponse>(uri, propertyUserField,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<BasicResponse> PutPropertyUserField(PropertyUserField propertyUserField)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPropertyUserField}";
var uri = new Uri(path);
return await _putRequest.Async<PropertyUserField, BasicResponse>(uri, propertyUserField,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<IEnumerable<AccountUserField>> PostAccountUserField(List<AccountUserField> accountUserField)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccountUserField}";
var uri = new Uri(path);
return await _postRequest.Async<List<AccountUserField>, IEnumerable<AccountUserField>>(uri, accountUserField,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
public async Task<IEnumerable<AccountUserField>> PutAccountUserField(List<AccountUserField> accountUserField)
{
var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccountUserField}";
var uri = new Uri(path);
return await _putRequest.Async<List<AccountUserField>, IEnumerable<AccountUserField>>(uri, accountUserField,
HttpUtilities.GetApiKeyHeaders(ClientKeyValue,
_apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0);
}
}
@@ -0,0 +1,45 @@
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Library.Internal.LcuHttpClient.HttpRequest;
namespace LCU.Api.Internal.DataCleanUp.DataAccess;
public class FileOperationsDao : IFileOperationsDao
{
private readonly FileOperationsConfiguration _fileOperationsConfiguration;
private readonly IPostRequest _postRequest;
private readonly IGetRequest _getRequest;
private const string ClientKeyValue = "DataCleanUp";
public FileOperationsDao(
FileOperationsConfiguration fileOperationsConfiguration,
IPostRequest postRequest,
IGetRequest getRequest
)
{
_fileOperationsConfiguration = fileOperationsConfiguration;
_postRequest = postRequest;
_getRequest = getRequest;
}
public async Task<string> GetFileContent(string finalFilePath)
{
var uri = new Uri($"{_fileOperationsConfiguration.FileOperationsUrl}{finalFilePath}");
return await _getRequest.StringResponseAsync(uri, 0);
}
public async Task<List<string>> WriteFile(WriteFileRequest writeFileRequest)
{
var path = $"{_fileOperationsConfiguration.FileOperationsUrl}{_fileOperationsConfiguration.WriteFile}";
var uri = new Uri(path);
return await _postRequest.AsyncWithNewton<WriteFileRequest, List<string>>(uri, writeFileRequest, 0);
}
public async Task<List<string>> BuildDynamicFileList(DynamicFileListRequest fileRequest)
{
var path = $"{_fileOperationsConfiguration.FileOperationsUrl}{_fileOperationsConfiguration.BuildDynamicFileList}";
var uri = new Uri(path);
return await _postRequest.Async<DynamicFileListRequest, List<string>>(uri, fileRequest, 0);
}
}
@@ -0,0 +1,62 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction;
using LCU.Library.Internal.DataCleanUpModel.Models;
using Microsoft.AspNetCore.Mvc;
namespace LCU.Api.Internal.DataCleanUp.DataAccess;
public interface ICoreApiWrapperDao
{
Task<IEnumerable<AgreePerson>> GetAgreePersonsWithHyphenatedUserIds();
Task<IEnumerable<string>> GetActiveCustodialAgreePersonNumbers();
Task<IEnumerable<AgreePerson>> GetActiveCustodialVruCardAgreementAgreePersons();
Task<IEnumerable<string>> GetVipSavingsToFund();
Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request);
Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request, List<string> includes);
Task<IEnumerable<ExternalDescription>> GetTransactionsExternalDescriptionsWithSsn();
Task<IEnumerable<string>> GetBranchCodeChangeAccountNumbers();
Task<IEnumerable<string>> GetGroupUpdateForAnalysisAccountNumbers();
Task<Agreement> GetAgreementByUserId(string userId);
Task<IReadOnlyCollection<PersonPostalAddress>> GetPersonPostalAddressByPersonNumber(int personNumber);
Task<IEnumerable<AccountsByMajorMinorBranchAndStatusResponse>> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request);
Task<PersonAddrLine> UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest);
Task<IEnumerable<PersonCheckHoldsUserField>> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize);
Task<AccessChannelPerson> UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey);
Task<AccessType> UpdateAccessType(AccessTypeUpdateRequest request);
Task<BasicResponse> UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request);
Task<BasicResponse> UpdateTransactionsExternalDescriptions(ExternalDescription request);
Task<List<BasicResponse>> PostFundsToAccount(List<FundsToAccountRequest> requests);
Task<BasicResponse> UpdateBranchCodesForAccountNumbers(AccountBranchUpdateRequest request);
Task<BasicResponse> UpdateAccountLoanToValue(AccountLtvUpdateRequest request);
Task<BasicResponse> UpdateAccountGroupForAnalysis(AccountAnalysisGroupMaintenanceRequest request);
Task<PersonUserField> UpdateAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request);
Task<PersonUserField> AddAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request);
Task<CreatedAccountResponse> PostOrganizationAccount(CreateOrganizationAccountRequest request);
Task<CreatedAccountResponse> PostPersonAccount(CreatePersonAccountRequest request);
Task<BasicResponse> PutOrganizationMaintenanceRequest(OrganizationMaintenanceRequest request);
Task<BasicResponse> PutAccountNicknameUpdateRequest(AccountNickNameUpdateRequest request);
Task<IEnumerable<Property>> GetPropertyNumberByAccountNumber(long accountNumber);
Task<BasicResponse> PutPersonUserField(PersonUserField personUserField);
Task<BasicResponse> PostPropertyUserField(PropertyUserField personUserField);
Task<BasicResponse> PutPropertyUserField(PropertyUserField personUserField);
Task<IEnumerable<PropertyUserField>> GetPropertyUserField(long accountNumber);
Task<Account> GetAccountByAccountNumber(long accountNumber);
Task<BasicResponse> UpdateAccountCreditReportType(AccountCreditReportTypeUpdateRequest request);
Task<IEnumerable<AccountUserField>> PostAccountUserField(List<AccountUserField> accountUserField);
Task<IEnumerable<AccountUserField>> PutAccountUserField(List<AccountUserField> accountUserField);
Task<IEnumerable<AccountUserField>> GetAccountUserField(long accountNumber);
}
@@ -0,0 +1,10 @@
using LCU.Library.Internal.FileOperationsModels.Models;
namespace LCU.Api.Internal.DataCleanUp.DataAccess;
public interface IFileOperationsDao
{
Task<string> GetFileContent(string finalFilePath);
Task<List<string>> WriteFile(WriteFileRequest request);
Task<List<string>> BuildDynamicFileList(DynamicFileListRequest request);
}
@@ -0,0 +1,13 @@
using LCU.Library.Internal.NotificationsModels.Models;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
namespace LCU.Api.Internal.DataCleanUp.DataAccess
{
public interface INotificationsDao
{
public HttpResponseMessage SendEmail(EmailRequest emailRequest);
}
}
@@ -0,0 +1,35 @@
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Library.Internal.NotificationsModels.Models;
using LCU.Library.Internal.LcuHttpClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using LCU.Library.Internal.LcuHttpClient.HttpRequest;
namespace LCU.Api.Internal.DataCleanUp.DataAccess
{
public class NotificationsDao : INotificationsDao
{
private readonly NotificationsApiConfiguration _notificationsApiConfiguration;
private readonly ILcuHttpClient _lcuHttpClient;
public NotificationsDao(ILcuHttpClient lcuHttpClient, NotificationsApiConfiguration emailConfiguration)
{
_lcuHttpClient = lcuHttpClient;
_notificationsApiConfiguration = emailConfiguration;
}
public HttpResponseMessage SendEmail(EmailRequest emailRequest)
{
var encoded = JsonConvert.SerializeObject(emailRequest);
Uri uri = new Uri(_notificationsApiConfiguration.EmailEndpoint);
var client = _lcuHttpClient.CreateClient(uri);
var c = new StringContent(encoded, Encoding.UTF8, "application/json");
HttpResponseMessage httpResponse = client.PostAsync(_notificationsApiConfiguration.EmailEndpoint, c).Result;
return httpResponse;
}
}
}
@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<WarningLevel>4</WarningLevel>
<NoWarn>1701;1702;8618;1591;8605</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<WarningLevel>4</WarningLevel>
<NoWarn>1701;1702;8618;1591;8605</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Automapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="CsvHelper" Version="28.0.1" />
<PackageReference Include="FileHelpers" Version="3.5.2" />
<PackageReference Include="LCU.Api.Internal.MaidBotLib" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.ApiResponse" Version="3.4.0" />
<PackageReference Include="LCU.Library.Internal.ApiSecurity" Version="1.0.2" />
<PackageReference Include="LCU.Library.Internal.Configuration" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.CoreApiWrapperModel" Version="2.27.14" />
<PackageReference Include="LCU.Library.Internal.Exceptions" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.FileOperationsModels" Version="4.1.0" />
<PackageReference Include="LCU.Library.Internal.LcuHttpClient" Version="1.17.0" />
<PackageReference Include="LCU.Library.Internal.LcuMassTransit" Version="1.0.0" />
<PackageReference Include="LCU.Library.Internal.LcuMassTransitModels" Version="1.1.0" />
<PackageReference Include="LCU.Library.Internal.Logging" Version="1.1.0" />
<PackageReference Include="LCU.Library.Internal.NotificationsModels" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="RabbitMQ.Client" Version="6.2.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="TimeZoneConverter" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LCU.Api.Internal.DataCleanUpLib\LCU.Api.Internal.DataCleanUpLib.csproj" />
<ProjectReference Include="..\LCU.Library.Internal.DataCleanUpModel\LCU.Library.Internal.DataCleanUpModel.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,17 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models
{
public class AccountCreditReportType
{
[Index(0)]
public long AccountNumber { get; set; }
[Index(1)]
public string BorrowerName { get; set; }
[Index(2)]
public decimal Balance { get; set; }
}
}
@@ -0,0 +1,21 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models;
public class AccountNickname
{
[Index(0)]
public int CustomerNumber { get; set; }
[Index(1)]
public long AccountNumber { get; set; }
[Index(2)]
public string AccountType { get; set; }
[Index(3)]
public string BusinessName { get; set; }
[Index(4)]
public string Nickname { get; set; }
}
@@ -0,0 +1,49 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models
{
public class BatchAddFundsToVipAccounts
{
[Index(0)]
public string NeedToFund { get; set; }
[Index(1)]
public string AccountNumber { get; set; }
[Index(2)]
public string MemberNumber { get; set; }
[Index(3)]
public string MemberName { get; set; }
[Index(4)]
public string NewMember { get; set; }
[Index(5)]
public string MajorCode { get; set; }
[Index(6)]
public string MinorCode { get; set; }
[Index(7)]
public string MinorDescription { get; set; }
[Index(8)]
public string AccountCreatedDate { get; set; }
[Index(9)]
public string InitialFundingDate { get; set; }
[Index(10)]
public string FundingAmount { get; set; }
[Index(11)]
public string FundingType { get; set; }
[Index(12)]
public string TransactinDescription { get; set; }
[Index(13)]
public string PromoCode { get; set; }
}
}
@@ -0,0 +1,73 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models;
public class BatchAddFundsToVipAccountsSummary
{
[Index(0)]
public string Funded { get; set; }
[Index(1)]
public string AmountFunded { get; set; }
[Index(2)]
public string AccountNumber { get; set; }
[Index(3)]
public string MemberNumber { get; set; }
[Index(4)]
public string MemberName { get; set; }
[Index(5)]
public string NewMember { get; set; }
[Index(6)]
public string MajorCode { get; set; }
[Index(7)]
public string MinorCode { get; set; }
[Index(8)]
public string MinorDescription { get; set; }
[Index(9)]
public string AccountCreatedDate { get; set; }
[Index(10)]
public string InitialFundingDate { get; set; }
[Index(11)]
public string FundingAmount { get; set; }
[Index(12)]
public string FundingType { get; set; }
[Index(13)]
public string TransactinDescription { get; set; }
[Index(14)]
public string PromoCode { get; set; }
public BatchAddFundsToVipAccountsSummary TransformNewSummary(bool funded, BatchAddFundsToVipAccounts vipAccount, double amountFunded)
{
var result = new BatchAddFundsToVipAccountsSummary()
{
Funded = funded ? "Yes" : "No",
AmountFunded = funded ? "$"+amountFunded.ToString() : "$0.00",
AccountNumber = vipAccount.AccountNumber,
MemberNumber = vipAccount.MemberNumber,
MemberName = vipAccount.MemberName,
NewMember = vipAccount.NewMember,
MajorCode = vipAccount.MajorCode,
MinorCode = vipAccount.MinorCode,
MinorDescription = vipAccount.MinorDescription,
AccountCreatedDate = vipAccount.AccountCreatedDate,
InitialFundingDate = vipAccount.InitialFundingDate,
FundingAmount = vipAccount.FundingAmount,
FundingType = vipAccount.FundingType,
TransactinDescription = vipAccount.TransactinDescription,
PromoCode = vipAccount.PromoCode
};
return result;
}
}
@@ -0,0 +1,119 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using System.ComponentModel.DataAnnotations.Schema;
namespace LCU.Api.Internal.DataCleanUp.Models;
public class CheckHoldsUserFieldValue
{
public CheckHoldsUserFieldValue()
{
}
public CheckHoldsUserFieldValue(PersonCheckHoldsUserField personUserField, DateTime checkHoldEndDate)
{
PersonCheckHoldsUser = personUserField;
CheckHoldEndDate = checkHoldEndDate;
}
public PersonCheckHoldsUserField PersonCheckHoldsUser { get; set; }
public DateTime CheckHoldEndDate { get; set; }
[NotMapped]
public bool NoAccounts_YesValue
{
get
{
//this person does not have any accounts
var value = !PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && !PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true;
return value == true;
}
}
[NotMapped]
public bool NoClosedInvalidActive_YesValue
{
get
{
//this person does not have any active accounts within valid check hold timeframe and no valid closed accounts
var value = PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && !PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true && PersonCheckHoldsUser.OldestActiveEffectiveDate > CheckHoldEndDate;
return value;
}
}
[NotMapped]
public bool NoActiveInvalidClosed_YesValue
{
get
{
//this person does not have any active accounts within valid check hold timeframe and no closed accounts within valid check hold timeframe
var value = !PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate <= CheckHoldEndDate;
return value;
}
}
[NotMapped]
public bool NoActiveClosedValid_NoValue
{
get
{
//this person does not have any valid active accounts and their closed account is within valid check hold timeframe
var value = !PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate >= CheckHoldEndDate;
return value;
}
}
[NotMapped]
public bool NoClosedActiveValid_NoValue
{
get
{
//this person does have active accounts within valid check hold timeframe and no valid closed accounts
var value = PersonCheckHoldsUser.OldestActiveEffectiveDate <= CheckHoldEndDate && !PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true;
return value;
}
}
[NotMapped]
public bool ActiveClosedValid_NoValue
{
get
{
//this person does have active accounts within valid check hold timeframe and closed accounts within valid check hold timeframe
var value = PersonCheckHoldsUser.OldestActiveEffectiveDate <= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate >= CheckHoldEndDate;
return value;
}
}
[NotMapped]
public bool ActiveInValidClosedValid_NoValue
{
get
{
//this person does not have active accounts within valid check hold timeframe and has closed accounts within valid check hold timeframe
var value = PersonCheckHoldsUser.OldestActiveEffectiveDate >= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate > CheckHoldEndDate;
return value;
}
}
[NotMapped]
public bool ActiveValidClosedInValid_NoValue
{
get
{
//this person does have active accounts within valid check hold timeframe and closed accounts not within valid check hold timeframe
var value = PersonCheckHoldsUser.OldestActiveEffectiveDate <= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate <= CheckHoldEndDate;
return value;
}
}
[NotMapped]
public bool ActiveInValidClosedInValid_YesValue
{
get
{
//this person does not have active accounts within valid check hold timeframe and closed accounts not within valid check hold timeframe
var value = PersonCheckHoldsUser.OldestActiveEffectiveDate >= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate <= CheckHoldEndDate;
return value;
}
}
}
@@ -0,0 +1,35 @@
using FileHelpers;
namespace LCU.Api.Internal.DataCleanUp.Models;
[DelimitedRecord(",")]
[IgnoreEmptyLines]
[IgnoreFirst(1)]
public class FannieMaeMortgage
{
public string ServicerNumber { get; set; }
[FieldConverter(ConverterKind.Int64)]
public long? FannieMaeLoanNumber { get; set; }
public string PoolIssueDate { get; set; }
public string ServicerName { get; set; }
[FieldConverter(ConverterKind.Int64)]
public long? ServicerLoanNumber { get; set; }
public string PropertyStreetAddress { get; set; }
public string PropertyCity { get; set; }
public string PropertyState { get; set; }
public string PropertyZipCode { get; set; }
public string PoolNumber { get; set; }
public string PfpStatus { get; set; }
}
@@ -0,0 +1,20 @@
namespace LCU.Api.Internal.DataCleanUp.Models
{
public class FannieMaeTotalBatchSummary
{
public List<FannieMaeUpdateResult> UpdateResults { get; set; }
public int TotalRecordsFound { get; set; }
public int TotalRecordsUpdated { get; set; }
public int TotalErrorRecords { get; set; }
public bool ErrorFileCreated { get; set; } = false;
public FannieMaeTotalBatchSummary(List<FannieMaeUpdateResult> updateResults, bool errorFileCreationSuccess)
{
UpdateResults = updateResults;
TotalErrorRecords = 0;
TotalRecordsUpdated = 0;
TotalRecordsFound = 0;
ErrorFileCreated = errorFileCreationSuccess;
}
}
}
@@ -0,0 +1,24 @@
namespace LCU.Api.Internal.DataCleanUp.Models;
public class FannieMaeUpdateResult
{
public List<FannieMaeMortgage> UpdateList { get; set; }
public List<string> ErrorList { get; set; }
public int TotalRecordsFound { get; set; }
public string Filename { get; set; }
public FannieMaeUpdateResult(string filename)
{
ErrorList = new List<string>();
UpdateList = new List<FannieMaeMortgage>();
TotalRecordsFound = 0;
Filename = filename;
}
public void AddStringToErrorList(FannieMaeMortgage record, string errorMessage)
{
var errorRecord = $"{record.ServicerLoanNumber}|{record.PoolNumber}|{record.PoolIssueDate}|{errorMessage}\n";
ErrorList.Add(errorRecord);
}
}
@@ -0,0 +1,13 @@
namespace LCU.Api.Internal.DataCleanUp.Models;
public class IndirectSavingsAccount
{
public long SavingsAccountNumber { get; set; }
public string MinorAccountType { get; set; }
public long BranchCode { get; set; }
public string TaxOwnerName { get; set; }
}
@@ -0,0 +1,7 @@
namespace LCU.Api.Internal.DataCleanUp.Models;
public class IndirectSavingsAccountResult
{
public string TotalAccountsFunded { get; set; }
public string TotalAccountsNotFunded { get; set; }
}
@@ -0,0 +1,34 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models;
public class IndirectSavingsAccountsSummary
{
[Index(0)]
public string AccountNumber { get; set; }
[Index(1)]
public string AmountFunded { get; set; }
[Index(2)]
public string BranchCode { get; set; }
[Index(3)]
public string Name { get; set; }
[Index(4)]
public string ErrorMessage { get; set; }
public IndirectSavingsAccountsSummary TransformNewSummary(long accountNumber, double amountFunded,
long branchCode, string name, string errorMessage)
{
var result = new IndirectSavingsAccountsSummary()
{
AccountNumber = accountNumber.ToString(),
AmountFunded = errorMessage == string.Empty ? amountFunded.ToString() : "0",
BranchCode = branchCode.ToString(),
Name = name.ToString(),
ErrorMessage = errorMessage
};
return result;
}
}
@@ -0,0 +1,58 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models;
public class MissingBatchSavings
{
[Index(0)]
public int CustomerNumber { get; set; }
[Index(1)]
public string FirstName { get; set; }
[Index(2)]
public string LastName { get; set; }
[Index(3)]
public string CustomerType { get; set; }
[Index(4)]
public string OrganizationName { get; set; }
[Index(5)]
public int CoreSavingsAccount { get; set; }
[Index(6)]
public string SavingsAccountNumber { get; set; }
[Index(7)]
public decimal SavingsAccountBalance { get; set; }
[Index(8)]
public int BranchCode { get; set; }
[Index(9)]
public int ControlPerson { get; set; }
[Index(10)]
public string ControlPersonNeeded { get; set; }
[Index(11)]
public string CustomerAddress1 { get; set; }
[Index(12)]
public string CustomerAddress2 { get; set; }
[Index(13)]
public string CustomerCity { get; set; }
[Index(14)]
public string CustomerState { get; set; }
[Index(15)]
public string CustomerZip { get; set; }
[Index(16)]
public string ControlPersonAssigned { get; set; }
}
@@ -0,0 +1,67 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models;
public class MissingBatchSavingsSummary
{
[Index(0)]
public int CustomerNumber { get; set; }
[Index(1)]
public string FirstName { get; set; }
[Index(2)]
public string LastName { get; set; }
[Index(3)]
public string CustomerType { get; set; }
[Index(4)]
public string OrganizationName { get; set; }
[Index(5)]
public string SavingsAccountNumber { get; set; }
[Index(6)]
public double AmountFunded { get; set; }
[Index(7)]
public int BranchCode { get; set; }
[Index(8)]
public string CustomerAddress1 { get; set; }
[Index(9)]
public string CustomerAddress2 { get; set; }
[Index(10)]
public string CustomerCity { get; set; }
[Index(11)]
public string CustomerState { get; set; }
[Index(12)]
public string CustomerZip { get; set; }
public MissingBatchSavingsSummary TransformNewSummary(MissingBatchSavings savingsRecord, double amountFunded, string savingsAccount)
{
var result = new MissingBatchSavingsSummary()
{
CustomerNumber = savingsRecord.CustomerNumber,
CustomerType = savingsRecord.CustomerType,
FirstName = savingsRecord.FirstName,
LastName = savingsRecord.LastName,
OrganizationName = savingsRecord.OrganizationName,
CustomerAddress1 = savingsRecord.CustomerAddress1,
CustomerAddress2 = savingsRecord.CustomerAddress2,
CustomerCity = savingsRecord.CustomerCity,
CustomerState = savingsRecord.CustomerState,
CustomerZip = savingsRecord.CustomerZip,
BranchCode = savingsRecord.BranchCode,
SavingsAccountNumber = savingsAccount,
AmountFunded = amountFunded
};
return result;
}
}
@@ -0,0 +1,76 @@
using FileHelpers;
namespace LCU.Api.Internal.DataCleanUp.Models.ParserModels;
[FixedLengthRecord()]
public class NcoaRecord
{
[FieldFixedLength(20)]
[FieldTrim(TrimMode.Right)]
public string UserId { get; set; }
[FieldFixedLength(1)]
public string NcoaType { get; set; }
[FieldFixedLength(6)]
public string ChangeDate { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string PrimaryName { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string CurrentAddressOne { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string CurrentAddressTwo { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string CurrentAddressThree { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string CurrentAddressFour { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string CurrentAddressFive { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string SecondaryName { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string BusinessName { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string NewAddressLine { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string City { get; set; }
[FieldFixedLength(2)]
public string StateCode { get; set; }
[FieldFixedLength(5)]
[FieldTrim(TrimMode.Right)]
public string ZipCode { get; set; }
[FieldFixedLength(5)]
[FieldTrim(TrimMode.Right)]
public string ZipSuffix { get; set; }
[FieldFixedLength(70)]
[FieldTrim(TrimMode.Both)]
public string UserIdTwo { get; set; }
[FieldFixedLength(60)]
[FieldTrim(TrimMode.Right)]
public string StatementCode { get; set; }
}
@@ -0,0 +1,26 @@
using CsvHelper.Configuration.Attributes;
namespace LCU.Api.Internal.DataCleanUp.Models
{
public class PmiCancel
{
[Index(0)]
public long LoanId { get; set; }
[Index(1)]
public string MemberName { get; set; }
[Index(2)]
public string LTVCancelDate { get; set; }
[Index(3)]
public string Midpoint { get; set; }
[Index(4)]
public string LoanCompanyName { get; set; }
[Ignore]
public string CurrentStatusCode { get; set; }
[Ignore]
public string CurrentStatus { get; set; }
[Ignore]
public long PropertyNumber { get; set; }
[Ignore]
public bool IsSuccessful { get; set; }
}
}
@@ -0,0 +1,37 @@
using CsvHelper.Configuration.Attributes;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Models
{
public class UpdatePmiCancelSummary
{
[Index(0)]
public long LoanId { get; set; }
[Index(1)]
public string MemberName { get; set; }
[Index(2)]
public long PropertyNumber { get; set; }
[Index(3)]
public string UpdatedDate { get; set; }
[Index(4)]
public string CurrentAccountStatus { get; set; }
[Index(5)]
public string SuccessOrFailMessage { get; set; }
public UpdatePmiCancelSummary TransformNewSummary(PmiCancel pmiCancel, string message)
{
var result = new UpdatePmiCancelSummary()
{
LoanId = pmiCancel.LoanId,
MemberName = pmiCancel.MemberName,
PropertyNumber = pmiCancel.PropertyNumber,
UpdatedDate = pmiCancel.LTVCancelDate,
CurrentAccountStatus = pmiCancel.CurrentStatus,
SuccessOrFailMessage = message
};
return result;
}
}
}
@@ -0,0 +1,28 @@
using Serilog;
namespace LCU.Api.Internal.DataCleanUp;
class Program
{
static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingcontext, config) =>
{
config.AddJsonFile("/app/config/mapped-appsettings/primary.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-api-security-configuration-internal-api-key-sets.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-database-connection.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-seq-api-key.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-connection-configuration-queue-user-name.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-connection-configuration-queue-password.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-saving-missing-requirements-defaults-funds-to-account-defaults-gl-account-number.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-indirect-gl-account-number.json", optional: true, reloadOnChange: true);
config.AddJsonFile("/vault/secrets/data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-funds-defaults-fund-amount-indirect-fund-amount.json", optional: true, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
.UseSerilog();
}
@@ -0,0 +1,52 @@
{
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"LCU.Api.Internal.DataCleanUp": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
},
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:63864/",
"sslPort": 0
}
}
}
@@ -0,0 +1,189 @@
using Serilog;
using CsvHelper;
using CsvHelper.Configuration;
using Newtonsoft.Json;
using System.Text;
using System.Globalization;
using TimeZoneConverter;
using LCU.Api.Internal.DataCleanUp.Models;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
namespace LCU.Api.Internal.DataCleanUp.Services
{
public class AddFundsToIndirectSavingsAccountsService : IAddFundsToIndirectSavingsAccountsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly IndirectSavingsRequirementsDefaults _indirectSavingsDefaults;
private DataCleanUpConfiguration _dataCleanUpConfiguration;
private List<IndirectSavingsAccountsSummary> _addFundsToIndirectAccountsSummaries = new List<IndirectSavingsAccountsSummary>();
public AddFundsToIndirectSavingsAccountsService(ICoreApiWrapperService coreApiWrapperService, IFileOperationsService fileOperationsService, IndirectSavingsRequirementsDefaults indirectSavingsDefaults, DataCleanUpConfiguration dataCleanUpConfiguration)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_indirectSavingsDefaults = indirectSavingsDefaults;
_dataCleanUpConfiguration = dataCleanUpConfiguration;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
var indirectFundRequest = JsonConvert.DeserializeObject<IndirectFundingRequest>(dataCleanUpRequest.DataCleanUpPayload);
ArgumentNullException.ThrowIfNull(indirectFundRequest);
try
{
var request = BuildRequestForAccountsToFund();
var accountsToFundList = await _coreApiWrapperService.GetAccountsByMajorMinorBranchAndStatus(request);
if (accountsToFundList != null)
{
Log.Information($"Data CleanUp # of Indirect Accounts To Be Funded {accountsToFundList.Count()} at {DateTime.Now}");
foreach (var accountToFund in accountsToFundList)
{
cleanUpResult = await HandleSavingsToFundsRequest(cleanUpResult, accountToFund);
}
}
await HandleExportResultsAddFundsToSavingsAccounts(indirectFundRequest);
}
catch (Exception exception)
{
Log.Error(exception, "Error while Handling Indirect Savings Account to Funds.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Handling Indirect Savings Account to Funds. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleSavingsToFundsRequest(DataCleanUpResult cleanUpResult, AccountsByMajorMinorBranchAndStatusResponse accountToBeFunded)
{
try
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack = new List<string>();
var listFundsToAccountsRequest = _coreApiWrapperService.BuildFundsToAccountRequests(accountToBeFunded.AccountNumber.ToString(), _indirectSavingsDefaults.GLAccountNumber, _indirectSavingsDefaults);
var basicResponse = await _coreApiWrapperService.PostFundsToAccount(listFundsToAccountsRequest);
ArgumentNullException.ThrowIfNull(basicResponse);
foreach (var response in basicResponse)
{
cleanUpResult.Successful = response.Success;
cleanUpResult.ResponseStack.AddRange(response.Errors);
}
var addFundstoAccountsSummary = HandleCreatingAccountSummary(accountToBeFunded, cleanUpResult);
_addFundsToIndirectAccountsSummaries.Add(addFundstoAccountsSummary);
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Handling Indirect Savings Account to Funds. " +
$"AccountNumber: {accountToBeFunded.AccountNumber}, " +
$"Exception:{exception}" + "</br>");
var addFundstoAccountsSummary = HandleCreatingAccountSummary(accountToBeFunded, cleanUpResult);
_addFundsToIndirectAccountsSummaries.Add(addFundstoAccountsSummary);
}
return cleanUpResult;
}
public AccountsByMajorMinorBranchAndStatusRequest BuildRequestForAccountsToFund()
{
var coreRequests = _indirectSavingsDefaults.FundingCoreRequests;
var request = new AccountsByMajorMinorBranchAndStatusRequest()
{
MajorTypes = coreRequests.MajorAccountTypes,
MinorTypes = coreRequests.MinorAccountTypes,
AccountStatuses = coreRequests.AccountStatusTypes,
BranchCodes = coreRequests.BranchCodeTypes
};
return request;
}
public IndirectSavingsAccountsSummary HandleCreatingAccountSummary(AccountsByMajorMinorBranchAndStatusResponse accountToBeFunded, DataCleanUpResult cleanUpResult)
{
var addFundstoAccountsSummary = new IndirectSavingsAccountsSummary();
return addFundstoAccountsSummary.TransformNewSummary(accountToBeFunded.AccountNumber, _indirectSavingsDefaults.FundsDefaults.FundAmount,
accountToBeFunded.BranchCode, accountToBeFunded.Name,
string.Join(";", cleanUpResult.ResponseStack.ToArray()));
}
public async Task HandleExportResultsAddFundsToSavingsAccounts(IndirectFundingRequest request)
{
try
{
var summaryTotal = new List<IndirectSavingsAccountResult>()
{
new IndirectSavingsAccountResult
{
TotalAccountsFunded = _addFundsToIndirectAccountsSummaries.Where(x => x.AmountFunded != "0").Count().ToString(),
TotalAccountsNotFunded = _addFundsToIndirectAccountsSummaries.Where(x => x.AmountFunded == "0").Count().ToString()
}
};
var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture)
{
HasHeaderRecord = true,
Delimiter = ",",
Encoding = Encoding.UTF8
};
var mem = new MemoryStream();
var writer = new StreamWriter(mem);
var csvWriter = new CsvWriter(writer, csvConfig);
ArgumentNullException.ThrowIfNull(csvWriter);
csvWriter.WriteHeader<IndirectSavingsAccountsSummary>();
csvWriter.NextRecord();
csvWriter.WriteRecords(_addFundsToIndirectAccountsSummaries);
csvWriter.NextRecord();
csvWriter.WriteHeader<IndirectSavingsAccountResult>();
csvWriter.NextRecord();
csvWriter.WriteRecords(summaryTotal);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
var dateString = GetCurrentDateTimeString("yyyy-MM-dd-HHmmss");
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = request.SummaryFileDestinationPath,
FileName = string.Join("-", request.Filename, dateString),
Overwrite = false,
Extension = "csv",
FileData = result,
};
await _fileOperationsService.WriteFile(writeFileRequest);
}
catch (Exception exception)
{
throw new Exception($"Export Add Funds Summary Error, {exception.Message}");
}
}
public string GetCurrentDateTimeString(string format)
{
var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone);
var currentDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, assumedTimezone);
return currentDateTime.ToString(format);
}
}
}
@@ -0,0 +1,70 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Configuration;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class AddFundsToVipSavingsAccountsService : IAddFundsToVipSavingsAccountsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly FundsToAccountDefaults _savingsFundsDefaults;
public AddFundsToVipSavingsAccountsService(ICoreApiWrapperService coreApiWrapperService, SavingsMissingRequirementsDefaults savingsFundsDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_savingsFundsDefaults = savingsFundsDefaults.FundsToAccountDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var accountNumbers = await _coreApiWrapperService.GetVipSavingsToFund();
ArgumentNullException.ThrowIfNull(accountNumbers);
Log.Information($"Data CleanUp # of Accounts {accountNumbers.Count()} at {DateTime.Now}");
foreach (var accountNumber in accountNumbers)
{
cleanUpResult = await HandleVipSavingsToFundsRequest(cleanUpResult, accountNumber);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while Handling Vip Savings Account to Funds.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Handling Vip Savings Account to Funds. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleVipSavingsToFundsRequest(DataCleanUpResult cleanUpResult, string accountNumber)
{
try
{
var basicResponse = await _coreApiWrapperService.PostFundsToAccount(accountNumber, _savingsFundsDefaults.FundsDefaults.FundAmount);
ArgumentNullException.ThrowIfNull(basicResponse);
foreach (var response in basicResponse)
{
if (!response.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(response.Errors);
}
}
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Handling Vip Savings Account to Funds. " +
$"AccountNumber: {accountNumber}, " +
$"Exception:{exception}" + "</br>");
}
return cleanUpResult;
}
}
@@ -0,0 +1,146 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Configuration;
using CsvHelper;
using LCU.Api.Internal.DataCleanUp.Models;
using System.Globalization;
using CsvHelper.Configuration;
using LCU.Library.Internal.FileOperationsModels.Models;
using System.Text;
namespace LCU.Api.Internal.DataCleanUp.Services
{
public class BatchAddFundsToVipSavingsAccountsService : IBatchAddFundsToVipSavingsAccountsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
private readonly FundsToAccountDefaults _savingsFundsDefaults;
private List<BatchAddFundsToVipAccountsSummary> _batchAddFundsToVipAccountsSummaries = new List<BatchAddFundsToVipAccountsSummary>();
public BatchAddFundsToVipSavingsAccountsService(ICoreApiWrapperService coreApiWrapperService, IFileOperationsService fileOperationsService, DataCleanupDefaults dataCleanupDefaults, SavingsMissingRequirementsDefaults savingsFundsDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_dataCleanupDefaults = dataCleanupDefaults;
_savingsFundsDefaults = savingsFundsDefaults.FundsToAccountDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var batchAddFundsFileData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.BatchAddFunds);
ArgumentNullException.ThrowIfNull(batchAddFundsFileData);
var textReader = new StringReader(batchAddFundsFileData);
ArgumentNullException.ThrowIfNull(textReader);
var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture);
var batchAddFundsCleanupList = csvReader.GetRecords<BatchAddFundsToVipAccounts>().ToList();
ArgumentNullException.ThrowIfNull(batchAddFundsCleanupList);
foreach (var accountToBeFunded in batchAddFundsCleanupList)
{
cleanUpResult = await HandleVipSavingsToFundsRequest(cleanUpResult, accountToBeFunded);
}
await HandleExportResultsBatchAddFundsToVipSavingsAccounts();
}
catch (Exception exception)
{
Log.Error(exception, "Error while Handling Batch Vip Savings Account to Funds.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Handling Vip Savings Account to Funds. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleVipSavingsToFundsRequest(DataCleanUpResult cleanUpResult, BatchAddFundsToVipAccounts accountToBeFunded)
{
try
{
bool fundsPostedSuccess = true;
var basicResponse = await _coreApiWrapperService.PostFundsToAccount(accountToBeFunded.AccountNumber, _savingsFundsDefaults.FundsDefaults.FundAmount);
ArgumentNullException.ThrowIfNull(basicResponse);
foreach (var response in basicResponse)
{
fundsPostedSuccess = fundsPostedSuccess && response.Success;
if (!response.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(response.Errors);
}
}
// Generate Summary Entry
var addFundstoVipAccountsSummary = new BatchAddFundsToVipAccountsSummary();
_batchAddFundsToVipAccountsSummaries.Add(addFundstoVipAccountsSummary.TransformNewSummary(fundsPostedSuccess, accountToBeFunded, _savingsFundsDefaults.FundsDefaults.FundAmount));
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Handling Batch Vip Savings Account to Funds. " +
$"AccountNumber: {accountToBeFunded.AccountNumber}, " +
$"Exception:{exception}" + "</br>");
var addFundstoVipAccountsSummary = new BatchAddFundsToVipAccountsSummary();
_batchAddFundsToVipAccountsSummaries.Add(addFundstoVipAccountsSummary.TransformNewSummary(false, accountToBeFunded, _savingsFundsDefaults.FundsDefaults.FundAmount));
}
return cleanUpResult;
}
public async Task HandleExportResultsBatchAddFundsToVipSavingsAccounts()
{
try
{
var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture)
{
HasHeaderRecord = true,
Delimiter = ",",
Encoding = Encoding.UTF8
};
var mem = new MemoryStream();
var writer = new StreamWriter(mem);
var csvWriter = new CsvWriter(writer, csvConfig);
ArgumentNullException.ThrowIfNull(csvWriter);
csvWriter.WriteHeader<BatchAddFundsToVipAccountsSummary>();
csvWriter.NextRecord();
csvWriter.WriteRecords(_batchAddFundsToVipAccountsSummaries);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = _dataCleanupDefaults.BatchAddFundsSummarySourcePath,
FileName = "BatchNeedToBeFundedSummary",
Overwrite = true,
Extension = "csv",
FileData = result,
};
await _fileOperationsService.WriteFile(writeFileRequest);
}
catch (Exception exception)
{
throw new Exception($"Export Batch Add Funds Summary Error, {exception.Message}");
}
}
}
}
@@ -0,0 +1,92 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Api.Internal.DataCleanUp.DataAccess;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class CloseCustodialVruAgreementsService : ICloseCustodialVruAgreementsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private const string NewStatusCode = "NEWSTATCD";
private const string CloseStatusValue = "CLOS";
private const string NewStatusReason = "NEWSTATREAS";
private const string VruAgreeTypeCode = "VRU";
private const string AutomatedSystemCleanupReason = "Automated System Cleanup";
public CloseCustodialVruAgreementsService(ICoreApiWrapperService coreApiWrapperService)
{
_coreApiWrapperService = coreApiWrapperService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var agreePerons = await _coreApiWrapperService.GetActiveCustodialVruCardAgreementAgreePersons();
ArgumentNullException.ThrowIfNull(agreePerons);
foreach (var agreePerson in agreePerons)
{
await HandleClosingCustodialVruAgreements(cleanUpResult, agreePerson);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while Closing Custodial Vru Agreements.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Closing Custodial Vru Agreements. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task HandleClosingCustodialVruAgreements(DataCleanUpResult cleanUpResult, AgreePerson agreePerson)
{
try
{
var detailTypes = new List<DetailType>()
{
new DetailType()
{
DetailTypeCode = NewStatusCode,
DetailValue = CloseStatusValue
},
new DetailType()
{
DetailTypeCode = NewStatusReason,
DetailValue = AutomatedSystemCleanupReason
}
};
var personAgreementDetailTypeRequest = new PersonAgreementDetailTypeRequest()
{
PersonNumber = agreePerson.PersonNumber,
AgreeNumber = agreePerson.AgreeNumber,
AgreeTypeCode = VruAgreeTypeCode,
DetailTypes = detailTypes
};
var result = await _coreApiWrapperService.UpdatePersonAgreementDetailTypes(personAgreementDetailTypeRequest);
ArgumentNullException.ThrowIfNull(result);
if (!result.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(result.Errors);
}
}
catch(Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Closing Custodial Vru Agreements. " +
$"PersonNumber: {agreePerson.PersonNumber}, " +
$"AgreeNumber: {agreePerson.AgreeNumber}, " +
$"Exception:{exception}");
}
}
}
@@ -0,0 +1,712 @@
using Serilog;
using System.Text.Json;
using LCU.Api.Internal.DataCleanUp.DataAccess;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class CoreApiWrapperService : ICoreApiWrapperService
{
private readonly ICoreApiWrapperDao _coreApiWrapperDao;
private readonly FundsToAccountDefaults _fundsToAccountDefaults;
private readonly DataCleanupDefaults _dataCleanupDefaults;
public CoreApiWrapperService(ICoreApiWrapperDao coreApiWrapperDao, SavingsMissingRequirementsDefaults savingsMissingRequirementsDefaults, DataCleanupDefaults dataCleanupDefaults)
{
_coreApiWrapperDao = coreApiWrapperDao;
_fundsToAccountDefaults = savingsMissingRequirementsDefaults.FundsToAccountDefaults;
_dataCleanupDefaults = dataCleanupDefaults;
}
public async Task<IEnumerable<string>> GetVipSavingsToFund()
{
try
{
var accountNumbers = await _coreApiWrapperDao.GetVipSavingsToFund();
return accountNumbers;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get Vip Savings for Funding.");
throw;
}
}
public async Task<IEnumerable<AccountsByMajorMinorBranchAndStatusResponse>> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request)
{
try
{
var response = await _coreApiWrapperDao.GetAccountsByMajorMinorBranchAndStatus(request);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get Accounts by MajorMinorBranchAndStatus.");
throw;
}
}
public async Task<IEnumerable<AgreePerson>> GetAgreePersonsWithHyphenatedUserIds()
{
try
{
var response = await _coreApiWrapperDao.GetAgreePersonsWithHyphenatedUserIds();
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to get Agree Persons With Hyphenated UserIds");
throw;
}
}
public async Task<IEnumerable<string>> GetActiveCustodialAgreePersonNumbers()
{
try
{
var response = await _coreApiWrapperDao.GetActiveCustodialAgreePersonNumbers();
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to get active custodial agree person numbers");
throw;
}
}
public async Task<IEnumerable<ExternalDescription>> GetTransactionsExternalDescriptionsWithSsn()
{
try
{
var externalDescriptionList = await _coreApiWrapperDao.GetTransactionsExternalDescriptionsWithSsn();
return externalDescriptionList;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to get Transactions External Descriptions with SSN");
throw;
}
}
public async Task<IEnumerable<AgreePerson>> GetActiveCustodialVruCardAgreementAgreePersons()
{
try
{
var response = await _coreApiWrapperDao.GetActiveCustodialVruCardAgreementAgreePersons();
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get Active Custodial Vru Card Agreement AgreePersons");
throw;
}
}
public async Task<Agreement?> GetAgreementByUserId(string userId)
{
try
{
var response = await _coreApiWrapperDao.GetAgreementByUserId(userId);
return response;
}
catch (Exception exception)
{
Log.Error(exception, $"Failure to Get Agreement by UserId, UserId: {userId}");
return null;
}
}
public async Task<IReadOnlyCollection<PersonPostalAddress>> GetPersonPostalAddressByPersonNumber(int personNumber)
{
try
{
var response = await _coreApiWrapperDao.GetPersonPostalAddressByPersonNumber(personNumber);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get PersonPostalAddress by PersonNumber");
throw;
}
}
public async Task<PersonAddrLine> UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest)
{
try
{
var response = await _coreApiWrapperDao.UpdateAddrLineByPersonNumber(ncoaRequest);
return response;
}
catch(Exception exception)
{
Log.Error("Failed to update AddrLine by PersonNumber");
throw exception;
}
}
public async Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request
)
{
try
{
var response = await _coreApiWrapperDao.GetCoreApiMessageAccessChannelPersons(request);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to get Access Channel Person");
throw;
}
}
public async Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request,
List<string> includes
)
{
try
{
var response = await _coreApiWrapperDao.GetCoreApiMessageAccessChannelPersons(request, includes);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to get Access Channel Person with Includes");
throw;
}
}
public async Task<AccessType> UpdateAccessType(AccessTypeUpdateRequest request)
{
try
{
var response = await _coreApiWrapperDao.UpdateAccessType(request);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to update AccessType");
throw;
}
}
public async Task<AccessChannelPerson> UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey)
{
try
{
var response = await _coreApiWrapperDao.UpdateAccessChannelPersons(request, updateKey);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to update Access Channel Person");
throw;
}
}
public async Task<BasicResponse> UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request)
{
try
{
var response = await _coreApiWrapperDao.UpdatePersonAgreementDetailTypes(request);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Person Agreement Detail Types");
throw;
}
}
public async Task<BasicResponse> UpdateTransactionsExternalDescriptions(ExternalDescription request)
{
try
{
var response = await _coreApiWrapperDao.UpdateTransactionsExternalDescriptions(request);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Transactions External Descriptions");
throw;
}
}
public List<FundsToAccountRequest> BuildFundsToAccountRequests(string accountNumber, double fundAmount)
{
var listFundsRequest = new List<FundsToAccountRequest>()
{
new FundsToAccountRequest()
{
AccountNumber = long.Parse(_fundsToAccountDefaults.GLAccountNumber),
Description = _fundsToAccountDefaults.Description,
TransactionAmount = fundAmount * -1,
TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeGL,
FundRequests = BuildFundRequests((double)(fundAmount * -1))
},
new FundsToAccountRequest()
{
AccountNumber = long.Parse(accountNumber),
Description = _fundsToAccountDefaults.Description,
TransactionAmount = fundAmount,
TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeDeposit,
FundRequests = BuildFundRequests((double)fundAmount)
}
};
return listFundsRequest;
}
public List<FundsToAccountRequest> BuildFundsToAccountRequests(string accountNumber, string glAccountNumber, FundsToAccountDefaults fundsToAccountDefaults)
{
var listFundsRequest = new List<FundsToAccountRequest>()
{
new FundsToAccountRequest()
{
AccountNumber = long.Parse(glAccountNumber),
Description = fundsToAccountDefaults.Description,
TransactionAmount = fundsToAccountDefaults.FundsDefaults.FundAmount * -1,
TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeGL,
FundRequests = BuildFundRequests((double)(fundsToAccountDefaults.FundsDefaults.FundAmount * -1))
},
new FundsToAccountRequest()
{
AccountNumber = long.Parse(accountNumber),
Description = _fundsToAccountDefaults.Description,
TransactionAmount = fundsToAccountDefaults.FundsDefaults.FundAmount,
TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeDeposit,
FundRequests = BuildFundRequests((double)fundsToAccountDefaults.FundsDefaults.FundAmount)
}
};
return listFundsRequest;
}
public List<FundRequest> BuildFundRequests(double fundAmount)
{
return new List<FundRequest>()
{
new FundRequest()
{
ClearingCategoryCode = _fundsToAccountDefaults.FundsDefaults.ClearingCategoryCode,
FundAmount = fundAmount,
FundTypeCode = _fundsToAccountDefaults.FundsDefaults.FundTypeCode,
FundTypeDetailCode = _fundsToAccountDefaults.FundsDefaults.FundTypeDetailCode
}
};
}
public async Task<IEnumerable<string>> GetBranchCodeChangeAccountNumbers()
{
try
{
var accountNumbers = await _coreApiWrapperDao.GetBranchCodeChangeAccountNumbers();
return accountNumbers;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get Accounts for Branch Codes.");
throw;
}
}
public async Task<BasicResponse> UpdateBranchCodesForAccountNumbers(string accountNumber, string branchCode)
{
try
{
var accountBranchCodeUpdateRequest = new AccountBranchUpdateRequest()
{
AccountNumber = long.Parse(accountNumber),
BranchOrganizationNumber = branchCode
};
var basicResponse = await _coreApiWrapperDao.UpdateBranchCodesForAccountNumbers(accountBranchCodeUpdateRequest);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Account with Branch Code.");
throw;
}
}
public async Task<BasicResponse> UpdateAccountLoanToValue(string accountNumber, double loanToValue)
{
try
{
var accountLtvUpdateRequest = new AccountLtvUpdateRequest()
{
AccountNumber = long.Parse(accountNumber),
LoanToValue = loanToValue
};
var basicResponse = await _coreApiWrapperDao.UpdateAccountLoanToValue(accountLtvUpdateRequest);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Account Loan to Value.");
throw;
}
}
public async Task<IEnumerable<string>> GetGroupUpdateForAnalysisAccountNumbers()
{
try
{
var accountNumbers = await _coreApiWrapperDao.GetGroupUpdateForAnalysisAccountNumbers();
return accountNumbers;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get Accounts for Group Update.");
throw;
}
}
public async Task<IEnumerable<PersonCheckHoldsUserField>> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize)
{
try
{
var personsForUserFieldList = await _coreApiWrapperDao.GetAtmCheckHoldsForPersonNumbers(resetStartDate, resetEndDate, fetchSize);
return personsForUserFieldList;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Get Person for Atm Check Holds.");
throw;
}
}
public async Task<PersonUserField> AddAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue)
{
try
{
var request = new PersonUserFieldRequest()
{
PersonNumber = personNumber,
UserFieldCode = _dataCleanupDefaults.MemberCheckHoldsUserFieldCode,
Value = userFieldValue
};
return await _coreApiWrapperDao.AddAtmCheckHoldsForPersonNumbers(request);
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Add Person for Atm Check Holds.");
throw;
}
}
public async Task<PersonUserField> UpdateAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue)
{
try
{
var request = new PersonUserFieldRequest()
{
PersonNumber = personNumber,
UserFieldCode = _dataCleanupDefaults.MemberCheckHoldsUserFieldCode,
Value = userFieldValue
};
return await _coreApiWrapperDao.UpdateAtmCheckHoldsForPersonNumbers(request);
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Add Person for Atm Check Holds.");
throw;
}
}
public async Task<BasicResponse> UpdateAccountGroupForAnalysis(string accountNumber)
{
try
{
var accountGroupForAnalysisUpdateRequest = new AccountAnalysisGroupMaintenanceRequest()
{
AccountNumber = long.Parse(accountNumber),
IsGenerateAnalysisStatement = true,
IsPrintAnalysisStatement = true,
IsUseForServiceCharge = true
};
var basicResponse = await _coreApiWrapperDao.UpdateAccountGroupForAnalysis(accountGroupForAnalysisUpdateRequest);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Account Group for Analysis.");
throw;
}
}
public async Task<CreatedAccountResponse> CreatePersonAccount(CreatePersonAccountRequest request)
{
try
{
var basicResponse = await _coreApiWrapperDao.PostPersonAccount(request);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Missing Savings For Person.");
throw;
}
}
public async Task<CreatedAccountResponse> CreateOrganizationAccount(CreateOrganizationAccountRequest request)
{
try
{
var json = JsonSerializer.Serialize(request);
var basicResponse = await _coreApiWrapperDao.PostOrganizationAccount(request);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Missing Savings For Org.");
throw;
}
}
public async Task<BasicResponse> AddControllingPersonOrganizationMaintenance(OrganizationMaintenanceRequest request)
{
try
{
var basicResponse = await _coreApiWrapperDao.PutOrganizationMaintenanceRequest(request);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Add Controlling Person For Org Maintenance.");
throw;
}
}
public async Task<List<BasicResponse>> PostFundsToAccount(List<FundsToAccountRequest> requests)
{
var basicResponse = await _coreApiWrapperDao.PostFundsToAccount(requests);
return basicResponse;
}
public async Task<List<BasicResponse>> PostFundsToAccount(string accountNumber, double fundAmount)
{
try
{
var fundsToAccountRequests = BuildFundsToAccountRequests(accountNumber, fundAmount);
var response = await PostFundsToAccount(fundsToAccountRequests);
return response;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Post Funds to Account.");
throw;
}
}
public async Task<BasicResponse> UpdateAccountNickname(long accountNumber, string accountDescription)
{
try
{
var request = new AccountNickNameUpdateRequest()
{
AccountNumber = accountNumber,
AccountDescription = accountDescription
};
var basicResponse = await _coreApiWrapperDao.PutAccountNicknameUpdateRequest(request);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Account Nickname.");
throw;
}
}
public async Task<BasicResponse> UpdateAccountCreditReportType(long accountNumber, string creditReportType)
{
try
{
var request = new AccountCreditReportTypeUpdateRequest()
{
AccountNumber = accountNumber,
CreditReportType = creditReportType
};
var basicResponse = await _coreApiWrapperDao.UpdateAccountCreditReportType(request);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Account Credit Report Type.");
throw;
}
}
public async Task<PmiCancel> GetPropertyNumber(PmiCancel pmiCancel)
{
try
{
if(pmiCancel == null)
{
Log.Error("PMI Cancel Object cannot be null");
throw new Exception("PMI Cancel Object cannot be null");
}
var account = await GetPropertyNumber(pmiCancel.LoanId);
if (account == null)
{
Log.Error("Account cannot be found");
throw new Exception("Account cannot be found");
}
var propertyInfo = await _coreApiWrapperDao.GetPropertyNumberByAccountNumber(pmiCancel.LoanId);
var propInfo = propertyInfo.ToList();
var pmiCancelResponse = new PmiCancel()
{
PropertyNumber = propInfo[0].PropertyNumber,
CurrentStatusCode = account.CurrentAccountStatusCode,
CurrentStatus = account.CurrentAccountStatusDescription,
};
return pmiCancelResponse;
}
catch(Exception exception)
{
Log.Error(exception, "Failure to get Property Information for PMI Cancel");
throw;
}
}
public async Task<Account> GetPropertyNumber(long accountNumber)
{
return await _coreApiWrapperDao.GetAccountByAccountNumber(accountNumber);
}
public async Task<BasicResponse> AddAccountPmiCancel(PmiCancel pmiCancel)
{
try
{
var propertyUserField = new PropertyUserField()
{
PropertyNumber = pmiCancel.PropertyNumber,
UserFieldCode = "PMIU",
Value = pmiCancel.LTVCancelDate
};
var basicResponse = await _coreApiWrapperDao.PostPropertyUserField(propertyUserField);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Add Account PMI Cancel Date");
throw;
}
}
public async Task<BasicResponse> UpdateAccountPmiCancel(PmiCancel pmiCancel)
{
try
{
var propertyUserField = new PropertyUserField()
{
PropertyNumber = pmiCancel.PropertyNumber,
UserFieldCode = "PMIU",
Value = pmiCancel.LTVCancelDate
};
var basicResponse = await _coreApiWrapperDao.PutPropertyUserField(propertyUserField);
return basicResponse;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to Update Account PMI Cancel Date");
throw;
}
}
public async Task<IEnumerable<PropertyUserField>> GetPropertyUserField(long propertyNumber)
{
try
{
var result = await _coreApiWrapperDao.GetPropertyUserField(propertyNumber);
return result;
}
catch (Exception exception)
{
Log.Error(exception, "Failure to find Person User Field");
throw;
}
}
public async Task<IEnumerable<AccountUserField>> GetAccountUserField(long accountNumber)
{
try
{
var response = await _coreApiWrapperDao.GetAccountUserField(accountNumber);
return response;
}
catch (Exception exception)
{
Log.Error(exception, $"Failure to Get Account User Field Code for {accountNumber}");
throw;
}
}
public async Task<IEnumerable<AccountUserField>> AddAccountUserField(long accountNumber, string userFieldCode, string value)
{
try
{
var accountUserField = new List<AccountUserField>()
{
new AccountUserField()
{
AccountNumber = accountNumber,
UserFieldCode = userFieldCode,
Value = value
}
};
var response = await _coreApiWrapperDao.PostAccountUserField(accountUserField);
return response;
}
catch (Exception exception)
{
Log.Error(exception, $"Failure to Add Account User Field {userFieldCode} for {accountNumber}");
throw;
}
}
public async Task<IEnumerable<AccountUserField>> UpdateAccountUserField(long accountNumber, string userFieldCode, string value)
{
try
{
var accountUserField = new List<AccountUserField>()
{
new AccountUserField()
{
AccountNumber = accountNumber,
UserFieldCode = userFieldCode,
Value = value
}
};
var response = await _coreApiWrapperDao.PutAccountUserField(accountUserField);
return response;
}
catch (Exception exception)
{
Log.Error(exception, $"Failure to Update Account User Field {userFieldCode} for {accountNumber}");
throw;
}
}
}
@@ -0,0 +1,109 @@
using Serilog;
using Newtonsoft.Json;
using LCU.Library.Internal.DataCleanUpModel.Enum;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.ApiResponse.Services;
using LCU.Api.Internal.MaidBotLib.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class DataCleanUpService : IDataCleanUpService
{
private readonly IHyphenatedUserIdCleanUpService _hyphenatedUserIdCleanUpService;
private readonly IDeactivateCustodialEAgreementsService _deactivateCustodialEAgreementsService;
private readonly ICloseCustodialVruAgreementsService _closeCustodialVruAgreementsService;
private readonly IMaskTransactionExternalDescriptionWithSsnService _maskTransactionExternalDescriptionWithSsnService;
private readonly IAddFundsToVipSavingsAccountsService _addFundsToVipSavingsAccountsService;
private readonly IBatchAddFundsToVipSavingsAccountsService _batchAddFundsToVipSavingsAccountsService;
private readonly IUpdateAdminBranchCodesByAccountNumberService _updateAdminBranchCodesByAccountNumberService;
private readonly IUpdateAccountLoanToValueService _updateAccountLoanToValueService;
private readonly IUpdateAccountGroupForAnalysisService _updateAccountGroupForAnalysisService;
private readonly IUpdatePersonForAtmHoldsService _updatePersonForAtmHoldsService;
private readonly IUpdateMissingBatchSavingsService _updateMissingBatchSavingsService;
private readonly IUpdateAccountNicknameService _updateAccountNicknameService;
private readonly IUpdateNcoaProcessService _updateNcoaProcessService;
private readonly IUpdateAccountCreditReportTypeService _updateAccountCreditReportTypeService;
private readonly IUpdateAccountPmiCancelService _updateAccountPmiCancelService;
private readonly IUpdateFannieMaeMortgageService _updateFannieMaeMortgageService;
private readonly IAddFundsToIndirectSavingsAccountsService _addFundsToIndirectSavingsAccountsService;
public DataCleanUpService(IHyphenatedUserIdCleanUpService hyphenatedUserIdCleanUpService,
IDeactivateCustodialEAgreementsService deactivateCustodialEAgreementsService,
ICloseCustodialVruAgreementsService closeCustodialVruAgreementsService,
IMaskTransactionExternalDescriptionWithSsnService maskTransactionExternalDescriptionWithSsnService,
IAddFundsToVipSavingsAccountsService addFundsToVipSavingsAccountsService,
IBatchAddFundsToVipSavingsAccountsService batchAddFundsToVipSavingsAccountsService,
IUpdateAdminBranchCodesByAccountNumberService updateAdminBranchCodesByAccountNumberService,
IUpdateAccountLoanToValueService updateAccountLoanToValueService,
IUpdateAccountGroupForAnalysisService updateAccountGroupForAnalysisService,
IUpdatePersonForAtmHoldsService updatePersonForAtmHoldsService,
IUpdateMissingBatchSavingsService updateMissingBatchSavingsService,
IUpdateAccountNicknameService updateAccountNicknameService,
IUpdateNcoaProcessService updateNcoaProcessService,
IUpdateAccountCreditReportTypeService updateAccountCreditReportTypeService,
IUpdateAccountPmiCancelService updateAccountPmiCancelService,
IUpdateFannieMaeMortgageService updateFannieMaeMortgageService,
IAddFundsToIndirectSavingsAccountsService addFundsToIndirectSavingsAccountsService)
{
_hyphenatedUserIdCleanUpService = hyphenatedUserIdCleanUpService;
_deactivateCustodialEAgreementsService = deactivateCustodialEAgreementsService;
_closeCustodialVruAgreementsService = closeCustodialVruAgreementsService;
_maskTransactionExternalDescriptionWithSsnService = maskTransactionExternalDescriptionWithSsnService;
_addFundsToVipSavingsAccountsService = addFundsToVipSavingsAccountsService;
_batchAddFundsToVipSavingsAccountsService = batchAddFundsToVipSavingsAccountsService;
_updateAdminBranchCodesByAccountNumberService = updateAdminBranchCodesByAccountNumberService;
_updateAccountLoanToValueService = updateAccountLoanToValueService;
_updateAccountGroupForAnalysisService = updateAccountGroupForAnalysisService;
_updatePersonForAtmHoldsService = updatePersonForAtmHoldsService;
_updateMissingBatchSavingsService = updateMissingBatchSavingsService;
_updateAccountNicknameService = updateAccountNicknameService;
_updateAccountPmiCancelService = updateAccountPmiCancelService;
_updateNcoaProcessService = updateNcoaProcessService;
_updateAccountCreditReportTypeService = updateAccountCreditReportTypeService;
_updateFannieMaeMortgageService = updateFannieMaeMortgageService;
_addFundsToIndirectSavingsAccountsService = addFundsToIndirectSavingsAccountsService;
}
public void DetermineCleanUp(DataCleanUpRequest request)
{
try
{
var result = request.CleanUpType switch
{
CleanUpTypes.HyphenatedUserId => _hyphenatedUserIdCleanUpService.CleanUp(request).Result,
CleanUpTypes.DeactivateCustodialEAgreements => _deactivateCustodialEAgreementsService.CleanUp(request).Result,
CleanUpTypes.CloseCustodialVruAgreements => _closeCustodialVruAgreementsService.CleanUp(request).Result,
CleanUpTypes.MaskTransactionExternalDescriptionWithSsn => _maskTransactionExternalDescriptionWithSsnService.CleanUp(request).Result,
CleanUpTypes.AddFundsToVipSavingsAccounts => _addFundsToVipSavingsAccountsService.CleanUp(request).Result,
CleanUpTypes.BatchAddFundsToVipSavingsAccounts => _batchAddFundsToVipSavingsAccountsService.CleanUp(request).Result,
CleanUpTypes.UpdateAdminBranchCodesByAccountNumber => _updateAdminBranchCodesByAccountNumberService.CleanUp(request).Result,
CleanUpTypes.UpdateAccountLoanToValue => _updateAccountLoanToValueService.CleanUp(request).Result,
CleanUpTypes.UpdateAccountGroupForAnalysis => _updateAccountGroupForAnalysisService.CleanUp(request).Result,
CleanUpTypes.UpdatePersonForCheckHolds => _updatePersonForAtmHoldsService.CleanUp(request).Result,
CleanUpTypes.UpdateMissingBatchSavings => _updateMissingBatchSavingsService.CleanUp(request).Result,
CleanUpTypes.UpdateAccountNickname => _updateAccountNicknameService.CleanUp(request).Result,
CleanUpTypes.UpdateNcoaProcess => _updateNcoaProcessService.CleanUp(request).Result,
CleanUpTypes.UpdateAccountCreditReportType => _updateAccountCreditReportTypeService.CleanUp(request).Result,
CleanUpTypes.UpdateAccountPmiCancel => _updateAccountPmiCancelService.CleanUp(request).Result,
CleanUpTypes.UpdateFannieMaeMortgage => _updateFannieMaeMortgageService.CleanUp(request).Result,
CleanUpTypes.AddFundsToIndirectSavingsAccounts => _addFundsToIndirectSavingsAccountsService.CleanUp(request).Result,
_ => throw new Exception("Error while Determining CleanUp")
};
ArgumentNullException.ThrowIfNull(result);
if (!result.Successful)
{
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
.Error($"Error while processing a Data Cleanup. Errors: {JsonConvert.SerializeObject(result.ResponseStack)}");
}
QueueReturnResponse.QueueResponse(request, result.Successful, result.ResponseStack);
}
catch (Exception exception)
{
Log.Error(exception, "Failure in DeterminCleanUp");
}
}
}
@@ -0,0 +1,134 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.Constants;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class DeactivateCustodialEAgreementsService : IDeactivateCustodialEAgreementsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private const string AccessTypeEAgreeementId = "WWW";
public DeactivateCustodialEAgreementsService(ICoreApiWrapperService coreApiWrapperService)
{
_coreApiWrapperService = coreApiWrapperService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var activeCustodialAgreePersonNumbers = await _coreApiWrapperService.GetActiveCustodialAgreePersonNumbers();
foreach (var personNumber in activeCustodialAgreePersonNumbers)
{
cleanUpResult = await HandleUpdateDeactivateCustodialEAgreement(cleanUpResult, personNumber);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while Deactivate Custodial Agreement CleanUp.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Deactivate Custodial EAgreement CleanUp. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleUpdateDeactivateCustodialEAgreement(DataCleanUpResult cleanUpResult, string personNumber)
{
try
{
var accessTypeUpdateRequest = await SetUpAccessTypeUpdateRequest(personNumber);
if (accessTypeUpdateRequest != null)
{
var updatedAccessType = await _coreApiWrapperService.UpdateAccessType(accessTypeUpdateRequest);
ArgumentNullException.ThrowIfNull(updatedAccessType);
if (updatedAccessType.IsActive)
{
throw new Exception($"AccessType has not been updated. Expected False but IsActive was true. " +
$"PersonNumber: {personNumber}");
}
}
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Failure to Deactivate Custodial EAgreement. " +
$"PersonNumber:{personNumber} " +
$"Exception Message:{exception.Message}");
}
return cleanUpResult;
}
public async Task<AccessTypeUpdateRequest?> SetUpAccessTypeUpdateRequest(string personNumber)
{
var coreApiMessage = await GetAccessChannelPersons(personNumber);
ArgumentNullException.ThrowIfNull(coreApiMessage.MessageBody);
var accessChannelPersons = coreApiMessage.MessageBody.ToList();
ArgumentNullException.ThrowIfNull(coreApiMessage?.MessageHeader?.UpdateKey);
AccessChannelPerson? accessChannelPerson = null;
AccessType? accessType = null;
foreach (var channelPerson in accessChannelPersons.ToList())
{
if (channelPerson.AccessTypes != null && channelPerson.AccessTypes.Any(accessType => accessType.Id == AccessTypeEAgreeementId && accessType.IsActive == true))
{
accessChannelPerson = channelPerson;
accessType = channelPerson.AccessTypes.FirstOrDefault(accessType => accessType.Id == AccessTypeEAgreeementId && accessType.IsActive == true);
}
}
if (accessType == null || accessChannelPerson == null)
{
return null;
}
accessType.IsActive = false;
accessType.UserId = null;
var accessTypeUpdateRequest = new AccessTypeUpdateRequest()
{
AccessType = accessType,
AccessChannelPersonId = accessChannelPerson.Id,
UpdateKey = (long)coreApiMessage.MessageHeader.UpdateKey
};
return accessTypeUpdateRequest;
}
public async Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetAccessChannelPersons(string personNumber)
{
long parsedPersonNumber;
if (!long.TryParse(personNumber, out parsedPersonNumber))
{
throw new Exception($"Person number was not able to be parsed to long. " +
$"PersonNumber:{personNumber}");
}
var request = new AccessChannelPersonsByPersonRequest()
{
PersonNumber = parsedPersonNumber,
ActiveOnly = true,
IncludeCards = false
};
var includes = new List<string>()
{
RequestIncludeConstants.AccessTypes
};
var coreApiMessage = await _coreApiWrapperService.GetCoreApiMessageAccessChannelPersons(request, includes);
return coreApiMessage;
}
}
@@ -0,0 +1,6 @@
namespace LCU.Api.Internal.DataCleanUp.Services.Emailers;
public interface INotificationsApiService
{
bool SendEmail(List<string> emailRecipients, string subject, string emailText);
}
@@ -0,0 +1,48 @@
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.DataAccess;
using LCU.Api.Internal.MaidBotLib.Models;
using LCU.Library.Internal.NotificationsModels.Models;
using Newtonsoft.Json;
using Serilog;
using System.Text;
namespace LCU.Api.Internal.DataCleanUp.Services.Emailers;
public class NotificationsApiService : INotificationsApiService
{
private readonly NotificationsApiConfiguration _notificationsApiConfiguration;
private readonly INotificationsDao _notificationsDao;
public NotificationsApiService(NotificationsApiConfiguration emailConfiguration, INotificationsDao notificationsDao)
{
_notificationsApiConfiguration = emailConfiguration;
_notificationsDao = notificationsDao;
}
public bool SendEmail(List<string> emailRecipients, string subject, string emailText)
{
try
{
var emailRequest = new EmailRequest
{
Recipient = emailRecipients,
Subject = subject,
Body = emailText
};
var httpResponse = _notificationsDao.SendEmail(emailRequest);
httpResponse.EnsureSuccessStatusCode();
}
catch (Exception ex)
{
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
.Error(ex, $"An exception was caught trying to send an email via Notifications API. Email Subject: {subject}");
return false;
}
return true;
}
}
@@ -0,0 +1,87 @@
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.DataAccess;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class FileOperationsService : IFileOperationsService
{
private readonly IFileOperationsDao _fileOperationsDao;
private readonly FileOperationsConfiguration _fileOperationsConfiguration;
public FileOperationsService(IFileOperationsDao fileOperationsDao,
FileOperationsConfiguration fileOperationsConfiguration)
{
_fileOperationsDao = fileOperationsDao;
_fileOperationsConfiguration = fileOperationsConfiguration;
}
public async Task<string> GetContentData(string filePath)
{
try
{
var filename = filePath.Replace("\\", "%5C");
var finalFilePath = new string($"{_fileOperationsConfiguration.GetFile}{filename}");
var response = await _fileOperationsDao.GetFileContent(finalFilePath);
return response;
}
catch (Exception exception)
{
throw new Exception($"Get Content Data Error, {exception.Message}");
}
}
public async Task<List<string>> WriteFile(WriteFileRequest request)
{
try
{
var response = await _fileOperationsDao.WriteFile(request);
return response;
}
catch (Exception exception)
{
throw new Exception($"Write File Error, {exception.Message}");
}
}
public Task<List<string>> BuildDynamicFileList(DynamicFileListRequest request)
{
try
{
var files = _fileOperationsDao.BuildDynamicFileList(request);
return files;
}
catch (Exception exception)
{
throw new Exception($"BuildDynamicFileList Error: {exception.Message}");
}
}
public DynamicFileListRequest BuildDynamicFileListRequest(NcoaUpdateRequest ncoaProcessRequest)
{
var request = new DynamicFileListRequest()
{
Path = ncoaProcessRequest.SourcePath,
Filename = ncoaProcessRequest.Filename,
DynamicFileSettings = ncoaProcessRequest.DynamicFileSettings,
};
return request;
}
public DynamicFileListRequest BuildDynamicFileListRequest(FannieMaeMortgageRequest fannieMaeMortgageRequest)
{
var request = new DynamicFileListRequest()
{
Path = fannieMaeMortgageRequest.SourcePath,
Filename = fannieMaeMortgageRequest.Filename,
DynamicFileSettings = fannieMaeMortgageRequest.DynamicFileSettings,
};
return request;
}
}
@@ -0,0 +1,95 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Api.Internal.DataCleanUp.DataAccess;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class HyphenatedUserIdCleanUpService : IHyphenatedUserIdCleanUpService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private const string HyphenReplacement = "C";
public HyphenatedUserIdCleanUpService(ICoreApiWrapperService coreApiWrapperService)
{
_coreApiWrapperService = coreApiWrapperService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var agreePersonsWithHyphenatedUserIds = await _coreApiWrapperService.GetAgreePersonsWithHyphenatedUserIds();
foreach (var agreePerson in agreePersonsWithHyphenatedUserIds)
{
cleanUpResult = await HandleUpdateOfHyphenatedUserId(cleanUpResult, agreePerson);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while Hyphenated UserId CleanUp.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Hyphenated UserId CleanUp. Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleUpdateOfHyphenatedUserId(DataCleanUpResult cleanUpResult, AgreePerson agreePerson)
{
try
{
var accessChannelPersonUpdateDetails = await DetermineAccessChannelPersonUpdateDetails(agreePerson);
var newUserId = accessChannelPersonUpdateDetails.accessChannelPerson.UserId.Replace("-", HyphenReplacement);
accessChannelPersonUpdateDetails.accessChannelPerson.UserId = newUserId;
var updatedAccessChannelPerson = await _coreApiWrapperService
.UpdateAccessChannelPersons(accessChannelPersonUpdateDetails.accessChannelPerson,
accessChannelPersonUpdateDetails.updateKey);
ArgumentNullException.ThrowIfNull(updatedAccessChannelPerson);
if (updatedAccessChannelPerson.UserId != newUserId)
{
throw new Exception($"UserId has not been updated. " +
$"Expected UserId:{newUserId}, " +
$"Returned UserId:{updatedAccessChannelPerson.UserId}");
}
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Failure to Update HyphenatedUserId. " +
$"PersonNumber:{agreePerson.PersonNumber} " +
$"UserId:{agreePerson.UserId}" +
$"Exception Message:{exception.Message}");
}
return cleanUpResult;
}
public async Task<(AccessChannelPerson accessChannelPerson, long updateKey)> DetermineAccessChannelPersonUpdateDetails(AgreePerson agreePerson)
{
var request = new AccessChannelPersonsByPersonRequest()
{
PersonNumber = agreePerson.PersonNumber,
ActiveOnly = true,
IncludeCards = false
};
var coreApiMessage = await _coreApiWrapperService.GetCoreApiMessageAccessChannelPersons(request);
ArgumentNullException.ThrowIfNull(coreApiMessage?.MessageHeader?.UpdateKey);
ArgumentNullException.ThrowIfNull(coreApiMessage.MessageBody);
var accessChannelPersons = coreApiMessage.MessageBody;
var accessChannelWithHyphenatedUserId = accessChannelPersons.FirstOrDefault(accessChannelPerson =>
accessChannelPerson.PersonNumber == agreePerson.PersonNumber &&
accessChannelPerson.UserId == agreePerson.UserId);
ArgumentNullException.ThrowIfNull(accessChannelWithHyphenatedUserId);
return (accessChannelWithHyphenatedUserId, (long)coreApiMessage.MessageHeader.UpdateKey);
}
}
@@ -0,0 +1,6 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IAddFundsToIndirectSavingsAccountsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IAddFundsToVipSavingsAccountsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,6 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IBatchAddFundsToVipSavingsAccountsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface ICloseCustodialVruAgreementsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,63 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
using LCU.Api.Internal.DataCleanUp.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
using LCU.Api.Internal.DataCleanUp.Configuration;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface ICoreApiWrapperService
{
public Task<IEnumerable<string>> GetVipSavingsToFund();
public Task<IEnumerable<AgreePerson>> GetAgreePersonsWithHyphenatedUserIds();
public Task<IEnumerable<string>> GetActiveCustodialAgreePersonNumbers();
Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request);
Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetCoreApiMessageAccessChannelPersons(
AccessChannelPersonsByPersonRequest request, List<string> includes);
public Task<IEnumerable<ExternalDescription>> GetTransactionsExternalDescriptionsWithSsn();
Task<IEnumerable<AgreePerson>> GetActiveCustodialVruCardAgreementAgreePersons();
public Task<IEnumerable<string>> GetBranchCodeChangeAccountNumbers();
public Task<IEnumerable<string>> GetGroupUpdateForAnalysisAccountNumbers();
public Task<IEnumerable<PersonCheckHoldsUserField>> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize);
public Task<Agreement?> GetAgreementByUserId(string userId);
public Task<IReadOnlyCollection<PersonPostalAddress>> GetPersonPostalAddressByPersonNumber(int personNumber);
public Task<IEnumerable<AccountsByMajorMinorBranchAndStatusResponse>> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request);
public Task<PersonAddrLine> UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest);
public Task<AccessChannelPerson> UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey);
public Task<AccessType> UpdateAccessType(AccessTypeUpdateRequest request);
public Task<BasicResponse> UpdateBranchCodesForAccountNumbers(string accountNumber, string branchCode);
public Task<BasicResponse> UpdateAccountLoanToValue(string accountNumber, double loanToValue);
public Task<BasicResponse> UpdateAccountGroupForAnalysis(string accountNumber);
public Task<PersonUserField> AddAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue);
public Task<PersonUserField> UpdateAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue);
public Task<BasicResponse> UpdateTransactionsExternalDescriptions(ExternalDescription request);
public Task<BasicResponse> UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request);
public Task<CreatedAccountResponse> CreatePersonAccount(CreatePersonAccountRequest request);
public Task<CreatedAccountResponse> CreateOrganizationAccount(CreateOrganizationAccountRequest request);
public Task<BasicResponse> AddControllingPersonOrganizationMaintenance(OrganizationMaintenanceRequest request);
public Task<List<BasicResponse>> PostFundsToAccount(string accountNumber, double fundAmount);
public Task<List<BasicResponse>> PostFundsToAccount(List<FundsToAccountRequest> requests);
public List<FundsToAccountRequest> BuildFundsToAccountRequests(string accountNumber, string glAccountNumber, FundsToAccountDefaults fundsToAccountDefaults);
public Task<BasicResponse> UpdateAccountNickname(long accountNumber, string accountDescription);
public Task<PmiCancel> GetPropertyNumber(PmiCancel pmiCancel);
public Task<BasicResponse> AddAccountPmiCancel(PmiCancel pmiCancel);
Task<BasicResponse> UpdateAccountPmiCancel(PmiCancel pmiCancel);
public Task<IEnumerable<PropertyUserField>> GetPropertyUserField(long propertyNumber);
public Task<BasicResponse> UpdateAccountCreditReportType(long accountNumber, string creditReportType);
public Task<IEnumerable<AccountUserField>> GetAccountUserField(long accountNumber);
public Task<IEnumerable<AccountUserField>> AddAccountUserField(long accountNumber, string userFieldCode, string value);
public Task<IEnumerable<AccountUserField>> UpdateAccountUserField(long accountNumber, string userFieldCode, string value);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IDataCleanUpService
{
void DetermineCleanUp(DataCleanUpRequest request);
}
@@ -0,0 +1,13 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IDeactivateCustodialEAgreementsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
Task<DataCleanUpResult> HandleUpdateDeactivateCustodialEAgreement(DataCleanUpResult cleanUpResult, string personNumber);
Task<AccessTypeUpdateRequest?> SetUpAccessTypeUpdateRequest(string personNumber);
Task<CoreApiMessage<IEnumerable<AccessChannelPerson>>> GetAccessChannelPersons(string personNumber);
}
@@ -0,0 +1,13 @@
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IFileOperationsService
{
public Task<string> GetContentData(string finalFilePath);
public Task<List<string>> WriteFile(WriteFileRequest request);
public Task<List<string>> BuildDynamicFileList(DynamicFileListRequest request);
public DynamicFileListRequest BuildDynamicFileListRequest(NcoaUpdateRequest ncoaProcessRequest);
public DynamicFileListRequest BuildDynamicFileListRequest(FannieMaeMortgageRequest fanniMaeMortgageRequest);
}
@@ -0,0 +1,11 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IHyphenatedUserIdCleanUpService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
Task<DataCleanUpResult> HandleUpdateOfHyphenatedUserId(DataCleanUpResult cleanUpResult, AgreePerson agreePerson);
Task<(AccessChannelPerson accessChannelPerson, long updateKey)> DetermineAccessChannelPersonUpdateDetails(AgreePerson agreePerson);
}
@@ -0,0 +1,8 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IMaskTransactionExternalDescriptionWithSsnService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
string MaskSsn(string descriptionWithSsn);
}
@@ -0,0 +1,23 @@
using LCU.Library.Internal.ApiResponse.Models;
using LCU.Library.Internal.DataCleanUpModel.Enum;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IQueueDataCleanUpService
{
Task QueueDataCleanUp(DataCleanUpRequest dataCleanUpRequest);
Task QueueDataCleanUpWithPayload<TRequest>(TRequest request, CleanUpTypes cleanUpType) where TRequest : ReturnResponse;
Task QueueHyphenatedUserIdCleanUp();
Task QueueDeactivateCustodialEAgreements();
Task QueueCloseCustodialVruAgreements();
Task QueueMaskTransactionExternalDescriptionWithSsn();
Task QueueAddFundsToVipSavingsAccounts();
Task QueueBatchAddFundsToVipSavingsAccounts();
Task QueueUpdateAdminBranchCodesByAccountNumber();
Task QueueUpdateAccountLoanToValue();
Task QueueUpdateAccountGroupForAnalysis();
Task QueueUpdateAccountNickname();
Task QueueUpdateAccountCreditReportType();
Task QueuePmiCancelUpdate();
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateAccountCreditReportTypeService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateAccountGroupForAnalysisService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateAccountLoanToValueService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,11 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services
{
public interface IUpdateAccountNicknameService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
}
@@ -0,0 +1,9 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services
{
public interface IUpdateAccountPmiCancelService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateAdminBranchCodesByAccountNumberService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,8 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateFannieMaeMortgageService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,7 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateMissingBatchSavingsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,8 @@
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdateNcoaProcessService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
}
@@ -0,0 +1,10 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using LCU.Library.Internal.DataCleanUpModel.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public interface IUpdatePersonForAtmHoldsService
{
Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest);
Task<DataCleanUpResult> HandlePersonForCheckHolds(DataCleanUpResult cleanUpResult, PersonCheckHoldsUserField person);
string DeterminePersonUserFieldValue(PersonCheckHoldsUserField person);
}
@@ -0,0 +1,106 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction;
using LCU.Api.Internal.DataCleanUp.DataAccess;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class MaskTransactionExternalDescriptionWithSsnService : IMaskTransactionExternalDescriptionWithSsnService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private const char DescriptionSplicer = '*';
private const int SplicedDescriptionLength = 5;
private const int SsnDescriptionIndex = 2;
private const int SsnEndSubStringIndex = 5;
private const string SsnMask = "XXXXX";
private const int SsnLength = 9;
public MaskTransactionExternalDescriptionWithSsnService(ICoreApiWrapperService coreApiWrapperService)
{
_coreApiWrapperService = coreApiWrapperService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var externalDescriptions = await _coreApiWrapperService.GetTransactionsExternalDescriptionsWithSsn();
ArgumentNullException.ThrowIfNull(externalDescriptions);
foreach (var externalDescription in externalDescriptions)
{
cleanUpResult = await HandleMaskingTransactionExternalDescriptionWithSsn(cleanUpResult, externalDescription);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while Masking SSN from Transaction External Description.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Masking SSN from Transaction External Description. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleMaskingTransactionExternalDescriptionWithSsn(DataCleanUpResult cleanUpResult, ExternalDescription externalDescription)
{
try
{
externalDescription.ExternalDescriptionText = MaskSsn(externalDescription.ExternalDescriptionText);
var basicResponse = await _coreApiWrapperService.UpdateTransactionsExternalDescriptions(externalDescription);
ArgumentNullException.ThrowIfNull(basicResponse);
if (!basicResponse.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(basicResponse.Errors);
}
}
catch(Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while Masking SSN from Transaction External Description. " +
$"ExternalDescriptionNumber: {externalDescription.ExternalDescriptionNumber}, " +
$"Exception:{exception}");
}
return cleanUpResult;
}
/// <summary>
/// If the description does not match the following pattern, the
/// SSN is not at the proper location, or if the SSN is formated differently then expected.
/// We will throw an exception and it will be logged as a fail for this transaction description.
///
/// Pattern: State of Wisc - SSI [Account Number] *[State of WI Tracking Number]*[SSN]*[MEMBER'S LAST NAME] [MEMBER'S FIRST NAME] *[SomeOtherNumber]\
/// </summary>
/// <param name="descriptionWithSsn"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public string MaskSsn(string descriptionWithSsn)
{
var descriptionSections = descriptionWithSsn.Split(DescriptionSplicer);
if(descriptionSections.Length != SplicedDescriptionLength)
{
throw new Exception($"Transaction External Description does not meet the pattern. " +
$"Was expecting {SplicedDescriptionLength} sections split by {DescriptionSplicer} " +
$"but there were {descriptionSections.Length} sections.");
}
var ssn = descriptionSections[SsnDescriptionIndex];
ArgumentNullException.ThrowIfNull(ssn);
if(ssn.Length != SsnLength)
{
throw new Exception($"The SSN pulled from the Transaction External Description does not meet the pattern." +
$"Was expecting SSN to be a lenght of {SsnLength} but it was {ssn.Length}.");
}
var newMaskSsn = ssn.Replace(ssn, $"{SsnMask}{ssn.Substring(SsnEndSubStringIndex)}" );
descriptionSections[SsnDescriptionIndex] = newMaskSsn;
var newDescription = string.Join(DescriptionSplicer, descriptionSections);
return newDescription;
}
}
@@ -0,0 +1,281 @@
using Serilog;
using MassTransit;
using Newtonsoft.Json;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.DataCleanUpModel.Enum;
using LCU.Library.Internal.LcuMassTransitModels;
using LCU.Library.Internal.Exceptions;
using LCU.Library.Internal.ApiResponse.Models;
using System;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class QueueDataCleanUpService : IQueueDataCleanUpService
{
private readonly ISendEndpoint _sendEndpoint;
private readonly ReceiveEndpointConfiguration _receiveEndpointConfiguration;
public QueueDataCleanUpService(IBusControl busControl,
ReceiveEndpointConfiguration receiveEndpointConfiguration)
{
_receiveEndpointConfiguration = receiveEndpointConfiguration;
_sendEndpoint = busControl.GetSendEndpoint(_receiveEndpointConfiguration.ReceiveEndpointUri).Result;
}
public async Task QueueDataCleanUp(DataCleanUpRequest dataCleanUpRequest)
{
try
{
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
var message = "Failed to Queue {dataCleanUpRequest.CleanUpType} Data Clean Up Request";
Log.Error($"{message}, Exception Message: {exception.Message}");
throw new ServiceException($"{message}, Exception Message: {exception.Message}");
}
}
public async Task QueueHyphenatedUserIdCleanUp()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.HyphenatedUserId
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue Hyphenated UserId Data Clean Up Request");
throw new ServiceException("Failed to Queue Hyphenated UserId Data Clean Up Request");
}
}
public async Task QueueDeactivateCustodialEAgreements()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue Deactivate Custodial EAgreements Request");
throw new ServiceException("Failed to Queue Deactivate Custodial EAgreements Request");
}
}
public async Task QueueCloseCustodialVruAgreements()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.CloseCustodialVruAgreements
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue Close Custodial Vru Agreements Request");
throw new ServiceException("Failed to Queue Close Custodial Vru Agreements Request");
}
}
public async Task QueueMaskTransactionExternalDescriptionWithSsn()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue Mask Transaction External Description with SSN");
throw new ServiceException("Failed to Queue Mask Transaction External Description with SSN");
}
}
public async Task QueueAddFundsToVipSavingsAccounts()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.AddFundsToVipSavingsAccounts
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue Add Funds To Vip Savings");
throw new ServiceException("Failed to Queue Add Funds To Vip Savings");
}
}
public async Task QueueBatchAddFundsToVipSavingsAccounts()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.BatchAddFundsToVipSavingsAccounts
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue Batch Add Funds To Vip Savings");
throw new ServiceException("Failed to Queue Batch Add Funds To Vip Savings");
}
}
public async Task QueueUpdateAdminBranchCodesByAccountNumber()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.UpdateAdminBranchCodesByAccountNumber
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue AdminBranchCodeChanges for Account Numbers");
throw new ServiceException("Failed to Queue AdminBranchCodeChanges for Account Numbers");
}
}
public async Task QueueUpdateAccountLoanToValue()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.UpdateAccountLoanToValue
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue UpdateAccountLoanToValue for Account Numbers");
throw new ServiceException("Failed to Queue UpdateAccountLoanToValue for Account Numbers");
}
}
public async Task QueueUpdateAccountGroupForAnalysis()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.UpdateAccountGroupForAnalysis
};
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token);
}
catch (Exception exception)
{
Log.Error(exception, "Failed to Queue UpdateAccountGroupForAnalysis for Account Numbers");
throw new ServiceException("Failed to Queue UpdateAccountGroupForAnalysis for Account Numbers");
}
}
public async Task QueueUpdateAccountNickname()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.UpdateAccountNickname
};
await QueueDataCleanUp(dataCleanUpRequest);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to Queue UpdateAccountNickname for Account Numbers");
throw new ServiceException("Failed to Queue UpdateAccountNickname for Account Numbers");
}
}
public async Task QueuePmiCancelUpdate()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.UpdateAccountPmiCancel
};
await QueueDataCleanUp(dataCleanUpRequest);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to Queue UpdatePmiCancel for Account Numbers");
throw new ServiceException("Failed to Queue UpdatePmiCancel for Account Numbers");
}
}
public async Task QueueDataCleanUpWithPayload<TRequest>(TRequest request, CleanUpTypes cleanUpType) where TRequest : ReturnResponse
{
try
{
ArgumentNullException.ThrowIfNull(request);
var queueRequest = new DataCleanUpRequest
{
CleanUpType = cleanUpType,
DataCleanUpPayload = JsonConvert.SerializeObject(request),
ResponseItems = request.ResponseItems
};
await QueueDataCleanUp(queueRequest);
}
catch (Exception ex)
{
Log.Error(ex, $"Failed to Queue Data Cleanup Type: {cleanUpType}");
throw new ServiceException($"Failed to Queue Data Cleanup Type: {cleanUpType}");
}
}
public async Task QueueUpdateAccountCreditReportType()
{
try
{
var dataCleanUpRequest = new DataCleanUpRequest()
{
CleanUpType = CleanUpTypes.UpdateAccountCreditReportType
};
await QueueDataCleanUp(dataCleanUpRequest);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to Queue UpdateAccountCreditReportType for Account Numbers");
throw new ServiceException("Failed to Queue UpdateAccountCreditReportType for Account Numbers");
}
}
}
@@ -0,0 +1,77 @@
using CsvHelper;
using Newtonsoft.Json;
using Serilog;
using System.Globalization;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Models;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateAccountCreditReportTypeService : IUpdateAccountCreditReportTypeService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private const string CreditReportType = "EXCL";
public UpdateAccountCreditReportTypeService(ICoreApiWrapperService coreApiWrapperService,
IFileOperationsService fileOperationsService)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
var creditTypeRequest = JsonConvert.DeserializeObject<CreditReportTypeRequest>(dataCleanUpRequest.DataCleanUpPayload);
try
{
var accountData = await _fileOperationsService.GetContentData(creditTypeRequest.SourcePath);
ArgumentNullException.ThrowIfNull(accountData);
var textReader = new StringReader(accountData);
ArgumentNullException.ThrowIfNull(textReader);
var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture);
var accountCreditReportTypeList = csvReader.GetRecords<AccountCreditReportType>().ToList();
ArgumentNullException.ThrowIfNull(accountCreditReportTypeList);
Log.Information($"Data CleanUp # of Accounts {accountCreditReportTypeList.Count()} at {DateTime.Now}");
foreach (var account in accountCreditReportTypeList)
{
cleanUpResult = await HandleAccountCreditReportType(cleanUpResult, account);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Account Credit Report Type.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Account Credit Report Type. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleAccountCreditReportType(DataCleanUpResult cleanUpResult, AccountCreditReportType account)
{
cleanUpResult.Successful = true;
try
{
var response = await _coreApiWrapperService.UpdateAccountCreditReportType(account.AccountNumber, CreditReportType);
if (!response.Success)
{
throw new Exception("Account Credit Report Type not updated.");
}
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while while updating Account Credit Report Type. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
}
@@ -0,0 +1,66 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Configuration;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateAccountGroupForAnalysisService : IUpdateAccountGroupForAnalysisService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
public UpdateAccountGroupForAnalysisService(ICoreApiWrapperService coreApiWrapperService, DataCleanupDefaults dataCleanupDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_dataCleanupDefaults = dataCleanupDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var accountNumbers = await _coreApiWrapperService.GetGroupUpdateForAnalysisAccountNumbers();
ArgumentNullException.ThrowIfNull(accountNumbers);
Log.Information($"Data CleanUp # of Accounts {accountNumbers.Count()} at {DateTime.Now}");
foreach (var accountNumber in accountNumbers)
{
cleanUpResult = await HandleAccountGroupForAnalysis(cleanUpResult, accountNumber);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Account for Group Analysis.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Account for Group Analysis. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleAccountGroupForAnalysis(DataCleanUpResult cleanUpResult, string accountNumber)
{
try
{
var basicResponse = await _coreApiWrapperService.UpdateAccountGroupForAnalysis(accountNumber);
ArgumentNullException.ThrowIfNull(basicResponse);
if (!basicResponse.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(basicResponse.Errors);
}
}
catch(Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Account for Group Analysis. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
}
@@ -0,0 +1,70 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUpLib.Repositories;
using LCU.Library.Internal.DataCleanUpModel.Entities;
using LCU.Api.Internal.DataCleanUp.Configuration;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateAccountLoanToValueService : IUpdateAccountLoanToValueService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
private readonly ILtvDataCleanUpRepository _ltvDataCleanUpRepository;
public UpdateAccountLoanToValueService(ICoreApiWrapperService coreApiWrapperService, ILtvDataCleanUpRepository ltvDataCleanUpRepository, DataCleanupDefaults dataCleanupDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_ltvDataCleanUpRepository = ltvDataCleanUpRepository;
_dataCleanupDefaults = dataCleanupDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var ltvDataCleanUpList = await _ltvDataCleanUpRepository.ListMinorAccountTypeAsync(_dataCleanupDefaults.LtvExcludedMinorAccountTypes);
ArgumentNullException.ThrowIfNull(ltvDataCleanUpList);
Log.Information($"Data CleanUp # of Accounts {ltvDataCleanUpList.Count()} at {DateTime.Now}");
foreach (var ltvDataCleanUp in ltvDataCleanUpList)
{
cleanUpResult = await HandleAccountLoanToValue(cleanUpResult, ltvDataCleanUp);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Account Loan To Value.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Account Loan To Value. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleAccountLoanToValue(DataCleanUpResult cleanUpResult, Ltv_DataCleanUp ltvDataCleanUp)
{
try
{
var basicResponse = await _coreApiWrapperService.UpdateAccountLoanToValue(ltvDataCleanUp.AccountNumber, ltvDataCleanUp.Ltv);
ArgumentNullException.ThrowIfNull(basicResponse);
if (!basicResponse.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(basicResponse.Errors);
}
}
catch(Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while while updating Account Loan To Value. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
}
@@ -0,0 +1,79 @@
using Serilog;
using CsvHelper;
using System.Globalization;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Models;
namespace LCU.Api.Internal.DataCleanUp.Services
{
public class UpdateAccountNicknameService : IUpdateAccountNicknameService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
public UpdateAccountNicknameService(ICoreApiWrapperService coreApiWrapperService,
IFileOperationsService fileOperationsService,
DataCleanupDefaults dataCleanupDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_dataCleanupDefaults = dataCleanupDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var accountData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.AccountNicknameSourcePath);
ArgumentNullException.ThrowIfNull(accountData);
var textReader = new StringReader(accountData);
ArgumentNullException.ThrowIfNull(textReader);
var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture);
var accountNicknameCleanupList = csvReader.GetRecords<AccountNickname>().ToList();
ArgumentNullException.ThrowIfNull(accountNicknameCleanupList);
Log.Information($"Data CleanUp # of Accounts {accountNicknameCleanupList.Count()} at {DateTime.Now}");
foreach (var account in accountNicknameCleanupList)
{
cleanUpResult = await HandleAccountNickname(cleanUpResult, account);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Account Nickname.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Missing Savings. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleAccountNickname(DataCleanUpResult cleanUpResult, AccountNickname account)
{
cleanUpResult.Successful = true;
try
{
var response = await _coreApiWrapperService.UpdateAccountNickname(account.AccountNumber, account.Nickname);
if (!response.Success)
{
throw new Exception("Account Nickname not updated.");
}
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while while updating Account Nickname. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
}
}
@@ -0,0 +1,157 @@
using CsvHelper;
using CsvHelper.Configuration;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.Models;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses;
using LCU.Library.Internal.DataCleanUpModel.Models;
using Newtonsoft.Json;
using Serilog;
using System.Globalization;
using System.Text;
namespace LCU.Api.Internal.DataCleanUp.Services
{
public class UpdateAccountPmiCancelService : IUpdateAccountPmiCancelService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
private readonly string closedStatus = "CLS";
private readonly string pmiustatus = "PMIU";
private readonly string success = "Account Successfully Updated";
private readonly string failure = "Not Updated. Account in Closed Status";
private List<UpdatePmiCancelSummary> _updatePmiCancelSummary = new List<UpdatePmiCancelSummary>();
public UpdateAccountPmiCancelService(ICoreApiWrapperService coreApiWrapperService,
IFileOperationsService fileOperationsService,
DataCleanupDefaults dataCleanupDefaults
)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_dataCleanupDefaults = dataCleanupDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var accountData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.PmiCancelSourcePath);
ArgumentNullException.ThrowIfNull(accountData);
var textReader = new StringReader(accountData);
ArgumentNullException.ThrowIfNull(textReader);
var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture);
var accountPmiCancelList = csvReader.GetRecords<PmiCancel>().ToList();
ArgumentNullException.ThrowIfNull(accountPmiCancelList);
Log.Information($"Data CleanUp # of Accounts {accountPmiCancelList.Count()} at {DateTime.Now}");
foreach (var account in accountPmiCancelList)
{
PmiCancel pmiCancel = new PmiCancel();
pmiCancel = await _coreApiWrapperService.GetPropertyNumber(account);
account.PropertyNumber = pmiCancel.PropertyNumber;
account.CurrentStatusCode = pmiCancel.CurrentStatusCode;
account.CurrentStatus = pmiCancel.CurrentStatus;
cleanUpResult = await HandleAccountPmiCancel(cleanUpResult, account);
}
await HandleExportResultsPmiCancelUpdate();
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Account PMI Cancel Date.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Account PMI Cancel Date. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleAccountPmiCancel(DataCleanUpResult cleanUpResult, PmiCancel account)
{
cleanUpResult.Successful = true;
UpdatePmiCancelSummary summary = new UpdatePmiCancelSummary();
BasicResponse response = null;
try
{
if (!account.CurrentStatusCode.Equals(closedStatus))
{
var result = await _coreApiWrapperService.GetPropertyUserField(account.PropertyNumber);
if (result != null && result.Any(c => c.UserFieldCode == pmiustatus))
{
response = await _coreApiWrapperService.UpdateAccountPmiCancel(account);
}
else
{
response = await _coreApiWrapperService.AddAccountPmiCancel(account);
}
if (!response.Success)
{
throw new Exception("Failure to Add or Update PMI Cancel Date");
}
_updatePmiCancelSummary.Add(summary.TransformNewSummary(account, success));
}
else
{
_updatePmiCancelSummary.Add(summary.TransformNewSummary(account, failure));
}
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while while updating or adding Account Pmi Cancel Date. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
public async Task HandleExportResultsPmiCancelUpdate()
{
try
{
var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture)
{
HasHeaderRecord = true,
Delimiter = ",",
Encoding = Encoding.UTF8
};
var mem = new MemoryStream();
var writer = new StreamWriter(mem);
var csvWriter = new CsvWriter(writer, csvConfig);
ArgumentNullException.ThrowIfNull(csvWriter);
csvWriter.WriteHeader<UpdatePmiCancelSummary>();
csvWriter.NextRecord();
csvWriter.WriteRecords(_updatePmiCancelSummary);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = _dataCleanupDefaults.PmiCancelSummaryPath,
FileName = "UpdatePmiCancelSummary",
Overwrite = true,
Extension = "csv",
FileData = result,
};
await _fileOperationsService.WriteFile(writeFileRequest);
}
catch (Exception exception)
{
throw new Exception($"Export Pmi Cancel Update Error, {exception.Message}");
}
}
}
}
@@ -0,0 +1,66 @@
using Serilog;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Configuration;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateAdminBranchCodesByAccountNumberService : IUpdateAdminBranchCodesByAccountNumberService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
public UpdateAdminBranchCodesByAccountNumberService(ICoreApiWrapperService coreApiWrapperService, DataCleanupDefaults dataCleanupDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_dataCleanupDefaults = dataCleanupDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var accountNumbers = await _coreApiWrapperService.GetBranchCodeChangeAccountNumbers();
ArgumentNullException.ThrowIfNull(accountNumbers);
Log.Information($"Data CleanUp # of Accounts {accountNumbers.Count()} at {DateTime.Now}");
foreach (var accountNumber in accountNumbers)
{
cleanUpResult = await HandleAdminBranchCodeChangeAccountNumbers(cleanUpResult, accountNumber);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while changing Admin Account Branch Codes.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while changing Admin Account Branch Codes. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleAdminBranchCodeChangeAccountNumbers(DataCleanUpResult cleanUpResult, string accountNumber)
{
try
{
var basicResponse = await _coreApiWrapperService.UpdateBranchCodesForAccountNumbers(accountNumber, _dataCleanupDefaults.DigitalBankingBranchCode);
ArgumentNullException.ThrowIfNull(basicResponse);
if (!basicResponse.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(basicResponse.Errors);
}
}
catch(Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while changing Admin Account Branch Codes. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
}
@@ -0,0 +1,285 @@
using FileHelpers;
using MassTransit;
using Newtonsoft.Json;
using Serilog;
using System.Globalization;
using TimeZoneConverter;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.Models;
using LCU.Api.Internal.DataCleanUp.Services.Emailers;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.MaidBotLib.Models;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateFannieMaeMortgageService : IUpdateFannieMaeMortgageService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly INotificationsApiService _notificationsApiService;
private readonly FannieMaeConfiguration _fannieMaeConfiguration;
private readonly DataCleanUpConfiguration _dataCleanUpConfiguration;
private readonly string _errorFileHeader = "DnaAccountNumber|InvestorPoolNumber|InvestorPoolDate\n";
private const string NoFilesMessage = "No files found for Update Fannie Mae Mortgage";
public UpdateFannieMaeMortgageService(ICoreApiWrapperService coreApiWrapperService,
IFileOperationsService fileOperationsService,
FannieMaeConfiguration fannieMaeConfiguration,
DataCleanUpConfiguration dataCleanUpConfiguration,
INotificationsApiService notificationsApiService)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_fannieMaeConfiguration = fannieMaeConfiguration;
_dataCleanUpConfiguration = dataCleanUpConfiguration;
_notificationsApiService = notificationsApiService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
var fannieMaeUpdateRequest = JsonConvert.DeserializeObject<FannieMaeMortgageRequest>(dataCleanUpRequest.DataCleanUpPayload);
var fannieMaeUpdateResultList = new List<FannieMaeUpdateResult>();
try
{
var reader = new FileHelperEngine<FannieMaeMortgage>();
var fileRequest = _fileOperationsService.BuildDynamicFileListRequest(fannieMaeUpdateRequest);
var fileList = await _fileOperationsService.BuildDynamicFileList(fileRequest);
if (!fileList.Any())
{
cleanUpResult.ResponseStack.Add(NoFilesMessage);
var emailSuccess = _notificationsApiService.SendEmail(fannieMaeUpdateRequest.EmailSummaryRecipients, _fannieMaeConfiguration.SummaryEmailSubject, NoFilesMessage);
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
foreach (var filename in fileList)
{
var updateResult = await HandleFileUpdate(filename, fannieMaeUpdateRequest, reader);
fannieMaeUpdateResultList.Add(updateResult);
}
cleanUpResult = await HandleBatchCompletion(fannieMaeUpdateResultList, cleanUpResult, fannieMaeUpdateRequest);
}
catch (Exception ex)
{
Log.Error(ex, "Error while updating Fannie Mae Mortgage.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Fannie Mae Mortgage." +
$"Exception:{ex}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<FannieMaeUpdateResult> ProcessFannieMaeRecord(FannieMaeMortgage entry, FannieMaeUpdateResult updateResult, string userFieldId, string userFieldValue)
{
try
{
if (await DetermineIfUserFieldExists((long)entry.ServicerLoanNumber!, userFieldId))
{
var updateResponse = await _coreApiWrapperService.UpdateAccountUserField((long)entry.ServicerLoanNumber, userFieldId, userFieldValue);
updateResult = HandleUserFieldResponse(updateResponse, updateResult, entry);
}
else
{
var addResponse = await _coreApiWrapperService.AddAccountUserField((long)entry.ServicerLoanNumber, userFieldId, userFieldValue);
updateResult = HandleUserFieldResponse(addResponse, updateResult, entry);
}
}
catch (Exception ex)
{
updateResult.AddStringToErrorList(entry, "Error while updating Account User Field " + userFieldId);
return updateResult;
}
return updateResult;
}
public async Task<bool> DetermineIfUserFieldExists(long serviceNumber, string userFieldCode)
{
var response = await _coreApiWrapperService.GetAccountUserField(serviceNumber);
return response.Any(c => c.UserFieldCode == userFieldCode);
}
private FannieMaeUpdateResult HandleUserFieldResponse(IEnumerable<AccountUserField> response, FannieMaeUpdateResult updateResult, FannieMaeMortgage entry)
{
if (response.Any())
{
updateResult.UpdateList.Add(entry);
}
else
{
var error = $"Fannie Mae Loan Record Failed: {entry.ServicerLoanNumber}";
updateResult.ErrorList = new List<string>() { error };
}
return updateResult;
}
#region "BatchFileCreation"
public async Task<DataCleanUpResult> HandleBatchCompletion(List<FannieMaeUpdateResult> fannieMaeUpdateResultList,
DataCleanUpResult cleanUpResult, FannieMaeMortgageRequest fanniMaeMortgageRequest)
{
var errorFileCreated = await CreateErrorFile(fannieMaeUpdateResultList, fanniMaeMortgageRequest.ErrorDestinationPath);
var totalBatchSummary = BuildTotalBatchSummary(fannieMaeUpdateResultList, errorFileCreated);
var batchResultSummaryText = CreateTotalBatchSummaryString(totalBatchSummary, fanniMaeMortgageRequest.ErrorDestinationPath);
foreach (var updateResult in totalBatchSummary.UpdateResults)
{
batchResultSummaryText += BuildFileUpdateSummary(updateResult);
}
var emailSuccess = _notificationsApiService.SendEmail(fanniMaeMortgageRequest.EmailSummaryRecipients, _fannieMaeConfiguration.SummaryEmailSubject, batchResultSummaryText);
batchResultSummaryText += $"Summary Email Request Successful: {emailSuccess}";
Log.Information(batchResultSummaryText);
cleanUpResult.ResponseStack.Add(batchResultSummaryText);
return cleanUpResult;
}
public async Task<bool> CreateErrorFile(List<FannieMaeUpdateResult> updateResultList, string fileDestinationPath)
{
try
{
var data = _errorFileHeader;
foreach (var updateResult in updateResultList)
{
foreach (var error in updateResult.ErrorList)
{
data += error;
}
}
if (data != _errorFileHeader)
{
var dateString = GetCurrentDateTimeString("yyyy-MM-dd-HHmmss");
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = fileDestinationPath,
FileName = dateString + _fannieMaeConfiguration.ErrorFileDefaultName,
Extension = ".csv",
FileData = data,
Overwrite = false
};
await _fileOperationsService.WriteFile(writeFileRequest);
return true;
}
}
catch (Exception ex)
{
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
.Error($"Error while writing Fannie Mae Error Record file. {ex.Message}");
Log.Error(ex, "Exception while trying to write Fannie Mae Error file");
return false;
}
return false;
}
public string BuildFileUpdateSummary(FannieMaeUpdateResult updateResult)
{
return $"--------------<br><br>Fannie Mae File In Batch Summary:<br><br>Filename: {updateResult.Filename}" +
$"<br><br>Total Records Received: {updateResult.TotalRecordsFound}<br><br>Total Records Updated: {updateResult.UpdateList.Count}" +
$"<br><br>Total Error Records: {updateResult.ErrorList.Count}<br><br>Total Records Processed: " +
$"{updateResult.UpdateList.Count + updateResult.ErrorList.Count}<br><br>";
}
public async Task<FannieMaeUpdateResult> HandleFileUpdate(string filename, FannieMaeMortgageRequest fannieMaeMortgageRequest, FileHelperEngine<FannieMaeMortgage> reader)
{
string formattedDate = string.Empty;
var updateResult = new FannieMaeUpdateResult(filename);
var fileData = await _fileOperationsService.GetContentData($"{fannieMaeMortgageRequest.FinalSourcePath}{filename}");
var fanniMaeUpdates = reader.ReadString(fileData);
updateResult.TotalRecordsFound = fanniMaeUpdates.Length;
foreach (var entry in fanniMaeUpdates)
{
if (!string.IsNullOrWhiteSpace(entry.PoolIssueDate))
{
DateTime date = DateTime.ParseExact(entry.PoolIssueDate, _fannieMaeConfiguration.FileDateFormat, CultureInfo.InvariantCulture);
formattedDate = date.ToString(_fannieMaeConfiguration.DnaDateFormat);
}
await ProcessFannieMaeRecord(entry, updateResult, _fannieMaeConfiguration.PoolDateUserFieldId, formattedDate);
await ProcessFannieMaeRecord(entry, updateResult, _fannieMaeConfiguration.PoolNbrUserFieldId, entry.PoolNumber);
}
return updateResult;
}
public async Task<bool> WriteFannieMaeErrorFile(string data, string destination)
{
try
{
var dateString = GetCurrentDateTimeString("yyyy-MM-dd-HHmmss");
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = destination,
FileName = dateString + _fannieMaeConfiguration.ErrorFileDefaultName,
Extension = ".csv",
FileData = data,
Overwrite = false
};
await _fileOperationsService.WriteFile(writeFileRequest);
return true;
}
catch (Exception ex)
{
Log.Error(ex, "Exception while trying to write Fannie Mae Error file");
return false;
}
}
#endregion
#region "EmailBatchSummary"
public string CreateTotalBatchSummaryString(FannieMaeTotalBatchSummary summary, string errorFileLocation = "")
{
return summary.ErrorFileCreated ?
$"Fannie Mae Update Total Batch Summary:<br><br>Total Files in Batch: {summary.UpdateResults.Count}<br><br>Total Records Received: " +
$"{summary.TotalRecordsFound}<br><br>Total Records Updated: {summary.TotalRecordsUpdated}<br><br>Total Error Records: " +
$"{summary.TotalErrorRecords}<br><br>Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}<br><br>" +
$"Error File Created: {summary.ErrorFileCreated}<br><br>Error File Location: {errorFileLocation}<br><br>"
:
$"Fannie Mae Update Total Batch Summary:<br><br>Total Files in Batch: {summary.UpdateResults.Count}<br><br>Total Records Received: " +
$"{summary.TotalRecordsFound}<br><br>Total Records Updated: {summary.TotalRecordsUpdated}<br><br>Total Error Records: " +
$"{summary.TotalErrorRecords}<br><br>Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}<br><br>" +
$"Error File Created: {summary.ErrorFileCreated}<br><br>";
}
public FannieMaeTotalBatchSummary BuildTotalBatchSummary(List<FannieMaeUpdateResult> updateResults, bool errorFileCreationSuccess)
{
var totalBatchSummary = new FannieMaeTotalBatchSummary(updateResults, errorFileCreationSuccess);
foreach (var updateResult in totalBatchSummary.UpdateResults)
{
totalBatchSummary.TotalRecordsFound += updateResult.TotalRecordsFound;
totalBatchSummary.TotalRecordsUpdated += updateResult.UpdateList.Count;
totalBatchSummary.TotalErrorRecords += updateResult.ErrorList.Count;
}
return totalBatchSummary;
}
#endregion
public string GetCurrentDateTimeString(string format)
{
var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone);
var currentDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, assumedTimezone);
return currentDateTime.ToString(format);
}
}
@@ -0,0 +1,243 @@
using Serilog;
using System.Globalization;
using System.Text;
using CsvHelper;
using CsvHelper.Configuration;
using LCU.Api.Internal.DataCleanUp.Models;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
using LCU.Api.Internal.DataCleanUp.Configuration;
using Newtonsoft.Json;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateMissingBatchSavingsService : IUpdateMissingBatchSavingsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
private readonly SavingsDefaults _savingsDefaults;
private List<MissingBatchSavingsSummary> _missingBatchSavingsSummaryList = new List<MissingBatchSavingsSummary>();
public UpdateMissingBatchSavingsService(ICoreApiWrapperService coreApiWrapperService, IFileOperationsService fileOperationsService, DataCleanupDefaults dataCleanupDefaults, SavingsMissingRequirementsDefaults savingsDefaults)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_dataCleanupDefaults = dataCleanupDefaults;
_savingsDefaults = savingsDefaults.SavingDefaults;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var missingSavingsFileData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.BatchSavingsSourcePath);
ArgumentNullException.ThrowIfNull(missingSavingsFileData);
var textReader = new StringReader(missingSavingsFileData);
ArgumentNullException.ThrowIfNull(textReader);
var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture);
var missingSavingsCleanupList = csvReader.GetRecords<MissingBatchSavings>().ToList();
ArgumentNullException.ThrowIfNull(missingSavingsCleanupList);
Log.Information($"Data CleanUp # of Accounts {missingSavingsCleanupList.Count()} at {DateTime.Now}");
foreach (var missingAccount in missingSavingsCleanupList)
{
cleanUpResult = await HandleMissingSavingsAccounts(cleanUpResult, missingAccount);
}
await HandleExportResultsBatchSavingsAccounts();
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Missing Savings.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Missing Savings. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandleMissingSavingsAccounts(DataCleanUpResult cleanUpResult, MissingBatchSavings missingAccount)
{
cleanUpResult.Successful = true;
CreatedAccountResponse createdAccountResponse = new CreatedAccountResponse();
try
{
if (missingAccount.CoreSavingsAccount == 0)
{
switch (missingAccount.CustomerType)
{
case "Person":
createdAccountResponse = await HandleUpdatingPersonSavingsAccounts(missingAccount);
break;
case "Organization":
createdAccountResponse = await HandleUpdatingOrganzationSavingsAccounts(missingAccount);
break;
default:
throw new Exception("Invalid Customer Type");
}
}
ArgumentNullException.ThrowIfNull(createdAccountResponse);
if (createdAccountResponse.BasicResponse != null && !createdAccountResponse.BasicResponse.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(createdAccountResponse.BasicResponse.Errors);
}
//Fund the account with either the new savings account number or the valid existing account from data
var fundAmount = Convert.ToDouble(5 - missingAccount.SavingsAccountBalance);
var accountNumberToFund = createdAccountResponse.AccountNumber == null ? missingAccount.SavingsAccountNumber : createdAccountResponse.AccountNumber.ToString();
ArgumentNullException.ThrowIfNull(accountNumberToFund);
var basicResponse = await HandleFundingBatchSavingsAccounts(accountNumberToFund, fundAmount);
ArgumentNullException.ThrowIfNull(basicResponse);
foreach (var response in basicResponse)
{
if (!response.Success)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.AddRange(response.Errors);
}
}
var missingBatchResult = new MissingBatchSavingsSummary();
//Transform to Summary for Export
var missingSavingsSummary = new MissingBatchSavingsSummary();
_missingBatchSavingsSummaryList.Add(missingSavingsSummary.TransformNewSummary(missingAccount, fundAmount, accountNumberToFund));
}
catch (Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while while updating Missing Savings Account. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
public async Task<CreatedAccountResponse> HandleUpdatingPersonSavingsAccounts(MissingBatchSavings missingSavings)
{
var request = new CreatePersonAccountRequest()
{
AccountDescription = _savingsDefaults.BatchAccountDescription,
BankOrganizationNumber = Convert.ToInt32(_savingsDefaults.BankOrganizationNumber),
CurrentAccountStatusCode = _savingsDefaults.CurrentAccountStatusCode,
CurrentMinorAccountTypeCode = _savingsDefaults.CurrentMinorAccountTypeCode,
DeliveryMethodCode = _savingsDefaults.DeliveryMethodCode,
OwnershipCode = _savingsDefaults.OwnershipCode,
IsTaxReportedForOwner = _savingsDefaults.IsTaxReportedForOwner,
IsTaxReportedForSigner = _savingsDefaults.IsTaxReportedForSigner,
IsValid = _savingsDefaults.IsValid,
MajorAccountTypeCode = _savingsDefaults.MajorAccountTypeCode,
PersonNumber = missingSavings.CustomerNumber,
FirstName = missingSavings.FirstName,
LastName = missingSavings.LastName,
BranchOrganizationNumber = missingSavings.BranchCode
};
return await _coreApiWrapperService.CreatePersonAccount(request);
}
public async Task<CreatedAccountResponse> HandleUpdatingOrganzationSavingsAccounts(MissingBatchSavings missingSavings)
{
var request = new CreateOrganizationAccountRequest()
{
AccountDescription = _savingsDefaults.BatchAccountDescription,
BankOrganizationNumber = Convert.ToInt32(_savingsDefaults.BankOrganizationNumber),
CurrentAccountStatusCode = _savingsDefaults.CurrentAccountStatusCode,
CurrentMinorAccountTypeCode = _savingsDefaults.CurrentMinorAccountTypeCode,
DeliveryMethodCode = _savingsDefaults.DeliveryMethodCode,
OwnershipCode = _savingsDefaults.OwnershipCode,
IsTaxReportedForOwner = _savingsDefaults.IsTaxReportedForOwner,
IsTaxReportedForSigner = _savingsDefaults.IsTaxReportedForSigner,
IsValid = _savingsDefaults.IsValid,
MajorAccountTypeCode = _savingsDefaults.MajorAccountTypeCode,
BranchOrganizationNumber = missingSavings.BranchCode,
OrganizationNumber = missingSavings.CustomerNumber,
};
//If there is a control person to assign from data and the org table does not have it assigned already, assign it
if (missingSavings.ControlPersonNeeded == "Y" && missingSavings.ControlPerson != 0)
{
var basicResponse = await HandleAddControllingPerson(missingSavings);
if (!basicResponse.Success)
{
throw new Exception($"Successful:{basicResponse.Success}, " +
$"ResponseStack: {string.Join("; ", basicResponse.Errors.ToArray())}");
}
}
return await _coreApiWrapperService.CreateOrganizationAccount(request);
}
public async Task<BasicResponse> HandleAddControllingPerson(MissingBatchSavings missingSavings)
{
var request = new OrganizationMaintenanceRequest()
{
ControllingPersonNumber = missingSavings.ControlPerson,
OrganizationNumber = missingSavings.CustomerNumber
};
BasicResponse basicResponse = await _coreApiWrapperService.AddControllingPersonOrganizationMaintenance(request);
ArgumentNullException.ThrowIfNull(basicResponse);
return basicResponse;
}
public async Task<List<BasicResponse>> HandleFundingBatchSavingsAccounts(string accountNumberToFund, double fundAmount)
{
return await _coreApiWrapperService.PostFundsToAccount(accountNumberToFund, fundAmount);
}
public async Task HandleExportResultsBatchSavingsAccounts()
{
try
{
var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture)
{
HasHeaderRecord = true,
Delimiter = ",",
Encoding = Encoding.UTF8
};
var mem = new MemoryStream();
var writer = new StreamWriter(mem);
var csvWriter = new CsvWriter(writer, csvConfig);
ArgumentNullException.ThrowIfNull(csvWriter);
csvWriter.WriteHeader<MissingBatchSavingsSummary>();
csvWriter.NextRecord();
csvWriter.WriteRecords(_missingBatchSavingsSummaryList);
writer.Flush();
var result = Encoding.UTF8.GetString(mem.ToArray());
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = _dataCleanupDefaults.BatchSavingsSummarySourcePath,
FileName = "MissingBatchSavingsSummary",
Overwrite = true,
Extension = "csv",
FileData = result,
};
await _fileOperationsService.WriteFile(writeFileRequest);
}
catch (Exception exception)
{
throw new Exception($"Export Missing Savings Error, {exception.Message}");
}
}
}
@@ -0,0 +1,430 @@
using FileHelpers;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.Models.ParserModels;
using LCU.Api.Internal.DataCleanUp.Services.Emailers;
using LCU.Api.Internal.DataCleanUp.Services.Validation;
using LCU.Library.Internal.FileOperationsModels.Models;
using LCU.Api.Internal.MaidBotLib.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
using LCU.Library.Internal.DataCleanUpModel.Models;
using Newtonsoft.Json;
using Serilog;
using System.Globalization;
using System.Text.RegularExpressions;
using TimeZoneConverter;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdateNcoaProcessService : IUpdateNcoaProcessService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly IFileOperationsService _fileOperationsService;
private readonly NcoaConfiguration _ncoaConfiguration;
private readonly DataCleanUpConfiguration _dataCleanUpConfiguration;
private readonly INcoaValidationService _ncoaValidationService;
private readonly INotificationsApiService _notificationsApiService;
private readonly string _errorFileHeader = "ChangeDate|UserId|PersonNumber|Name|CurrentAddress1|CurrentAddress2|CurrentAddress3|CurrentAddress4|CurrentAddress5" +
"|New Address|City|State|Zip|ZipSuffix|ErrorMessage\n";
public UpdateNcoaProcessService(ICoreApiWrapperService coreApiWrapperService,
IFileOperationsService fileOperationsService,
NcoaConfiguration ncoaConfiguration,
DataCleanUpConfiguration dataCleanUpConfiguration,
INcoaValidationService ncoaValidationService,
INotificationsApiService notificationsApiService)
{
_coreApiWrapperService = coreApiWrapperService;
_fileOperationsService = fileOperationsService;
_ncoaConfiguration = ncoaConfiguration;
_dataCleanUpConfiguration = dataCleanUpConfiguration;
_ncoaValidationService = ncoaValidationService;
_notificationsApiService = notificationsApiService;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
var ncoaProcessRequest = JsonConvert.DeserializeObject<NcoaUpdateRequest>(dataCleanUpRequest.DataCleanUpPayload);
var ncoaUpdateResultList = new List<NcoaUpdateResult>();
var exclusionList = new List<string>();
try
{
var reader = new FileHelperEngine<NcoaRecord>();
var fileRequest = _fileOperationsService.BuildDynamicFileListRequest(ncoaProcessRequest);
var fileList = await _fileOperationsService.BuildDynamicFileList(fileRequest);
if (!fileList.Any())
{
var noFilesFound = "No files found for Update NCOA Process";
cleanUpResult.ResponseStack.Add(noFilesFound);
var emailSuccess = _notificationsApiService.SendEmail(ncoaProcessRequest.EmailSummaryRecipients, _ncoaConfiguration.SummaryEmailSubject, noFilesFound);
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
exclusionList = await GetExclusionList(ncoaProcessRequest.ExclusionFilePath);
foreach (var filename in fileList)
{
var updateResult = await HandleFileUpdate(filename, ncoaProcessRequest, reader, exclusionList);
ncoaUpdateResultList.Add(updateResult);
}
cleanUpResult = await HandleBatchCompletion(ncoaUpdateResultList, cleanUpResult, ncoaProcessRequest);
}
catch (Exception ex)
{
Log.Error(ex, "Error while updating NCOA Process.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating NCOA Process. " +
$"Exception:{ex}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public PersonAddrLine CheckForPoBoxAddressLineType(PersonAddrLine request)
{
if (request.AddressLine1.Contains(_ncoaConfiguration.PoBoxLabel))
{
request.AddressLineTypeCode1 = _ncoaConfiguration.PoBoxAddressTypeLabel;
}
return request;
}
public PersonAddrLine MapPersonAddrLine(int personNumber, PersonPostalAddress currentAddress, NcoaRecord ncoaRecord)
{
var currentDateTime = GetCurrentDateTimeString("yyyy-MM-ddTHH:mm:ss.fffK");
var coreNcoaRequest = new PersonAddrLine()
{
PersonNumber = personNumber,
Id = _ncoaConfiguration.PrimaryAddressLabel,
AddressUseCode = _ncoaConfiguration.PrimaryAddressLabel,
AddressNumber = currentAddress.AddressNumber,
AddressLine1 = ncoaRecord.NewAddressLine,
AddressLineTypeCode1 = _ncoaConfiguration.StreetTypeLabel,
AddressLine2 = null,
AddressLineTypeCode2 = null,
AddressLine3 = null,
AddressLineTypeCode3 = null,
CityName = ConvertToTitleCase(ncoaRecord.City.ToLower()),
CountrySubdivisionCode = ncoaRecord.StateCode,
PostalCode = ncoaRecord.ZipCode,
ZipPlus = ncoaRecord.ZipSuffix.Replace("-", ""),
CountryCode = _ncoaConfiguration.UsaLabel,
Url = _ncoaConfiguration.UrlBase.Replace(_ncoaConfiguration.PersonNumberLabel, personNumber.ToString()),
IsPerformIRSCorrection = false,
EffectiveDate = GetCurrentDateTimeString("yyyy-MM-dd")
};
coreNcoaRequest = CheckForPoBoxAddressLineType(coreNcoaRequest);
return coreNcoaRequest;
}
public async Task<bool> WriteNcoaErrorFile(string data, string destination)
{
try
{
var dateString = GetCurrentDateTimeString("yyyyMMdd");
var writeFileRequest = new WriteFileRequest()
{
DestinationPath = destination,
FileName = dateString + _ncoaConfiguration.ErrorFileDefaultName,
Extension = ".csv",
FileData = data,
Overwrite = false
};
await _fileOperationsService.WriteFile(writeFileRequest);
return true;
}
catch (Exception ex)
{
Log.Error(ex, "Exception while trying to WriteNCOA Error file");
return false;
}
}
public string GetCurrentDateTimeString(string format)
{
var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone);
var currentDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, assumedTimezone).Date;
return currentDateTime.ToString(format);
}
public string ConvertToTitleCase(string entry)
{
var textinfo = new CultureInfo("en-US", false).TextInfo;
return textinfo.ToTitleCase(entry);
}
public async Task<(DataCleanUpResult cleanUpResult, bool errorFileCreationSuccess)> CreateErrorFile(List<NcoaUpdateResult> updateResultList, string fileDestinationPath, DataCleanUpResult cleanUpResult)
{
var errorFileCreationSuccess = false;
var data = _errorFileHeader;
try
{
foreach (var updateResult in updateResultList)
{
if (updateResult.ErrorList.Count < 1)
{
cleanUpResult.ResponseStack.Add($"0 Error Records for file: {updateResult.Filename}");
continue;
}
foreach (var error in updateResult.ErrorList)
{
data += error;
}
}
errorFileCreationSuccess = await WriteNcoaErrorFile(data, fileDestinationPath);
if (!errorFileCreationSuccess)
{
throw new Exception("Affected Records: " + data);
}
}
catch (Exception ex)
{
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
.Error($"Error while writing NCOAError Record file. {ex.Message}");
cleanUpResult.ResponseStack.Add($"Error while writing {_ncoaConfiguration.ErrorFileDefaultName} file. Error file not produced. Data available in Logs.");
}
return (cleanUpResult, errorFileCreationSuccess);
}
public async Task<NcoaUpdateResult> ProcessNcoaRecord(NcoaRecord entry, NcoaUpdateResult updateResult,
NcoaUpdateRequest ncoaProcessRequest, List<string> exclusionList)
{
if (_ncoaValidationService.IsBusinessRecord(entry))
{
updateResult.AddStringToErrorList(entry, "Record appears to be a business account");
return updateResult;
}
var currentAgreement = await _coreApiWrapperService.GetAgreementByUserId(entry.UserId);
var personNumber = _ncoaValidationService.ParsePersonNumber(currentAgreement);
if (personNumber <= 0)
{
updateResult.AddStringToErrorList(entry, "Unable to parse or find PersonNumber from UserId");
return updateResult;
}
if (_ncoaValidationService.AgreementHasOrgNumber(currentAgreement))
{
updateResult.AddStringToErrorList(entry, "Record has an OrgNumber in Agreement from DNA");
return updateResult;
}
var personPostalAddressList = await _coreApiWrapperService.GetPersonPostalAddressByPersonNumber(personNumber);
var primaryAddress = _ncoaValidationService.IsAddrUseCodeFound(personPostalAddressList, _ncoaConfiguration.PrimaryAddressLabel);
if (primaryAddress == null)
{
updateResult.AddStringToErrorList(entry, "Unable to find a primary address by PersonNumber", personNumber.ToString());
return updateResult;
}
if (_ncoaValidationService.IsAddressUpdatedRecently(primaryAddress, ncoaProcessRequest.ExclusionDays, GetCurrentDateTimeString("yyyy-MM-dd")))
{
updateResult.AddStringToErrorList(entry, $"Primary Address has been updated within the last " +
$"{Math.Abs(ncoaProcessRequest.ExclusionDays).ToString()} days.", personNumber.ToString());
return updateResult;
}
var coreNcoaRequest = MapPersonAddrLine(personNumber, primaryAddress, entry);
if (_ncoaValidationService.IsAddrLineTooLong(coreNcoaRequest.AddressLine1))
{
updateResult.AddStringToErrorList(entry, "New Address Record is greater than 40 characters. Requires manual line split", personNumber.ToString());
return updateResult;
}
if(_ncoaValidationService.IsOnExclusionList(coreNcoaRequest.PersonNumber, exclusionList))
{
updateResult.AddStringToErrorList(entry, "Record matches an entry in exclusion list", personNumber.ToString());
return updateResult;
}
try
{
var CoreResult = await _coreApiWrapperService.UpdateAddrLineByPersonNumber(coreNcoaRequest);
}
catch (Exception ex)
{
updateResult.AddStringToErrorList(entry, "Error while upating address in CoreApi", coreNcoaRequest.PersonNumber.ToString());
return updateResult;
}
updateResult.AddPersonAddrLineToUpdateList(coreNcoaRequest);
return updateResult;
}
public async Task<DataCleanUpResult> HandleBatchCompletion(List<NcoaUpdateResult> ncoaUpdateResultList,
DataCleanUpResult cleanUpResult, NcoaUpdateRequest ncoaProcessRequest)
{
var errorFileResult = await CreateErrorFile(ncoaUpdateResultList, ncoaProcessRequest.ErrorDestinationPath, cleanUpResult);
cleanUpResult = errorFileResult.cleanUpResult;
var totalBatchSummary = BuildTotalBatchSummary(ncoaUpdateResultList, errorFileResult.errorFileCreationSuccess);
var batchResultSummaryText = CreateTotalBatchSummaryString(totalBatchSummary, ncoaProcessRequest.ErrorDestinationPath);
foreach(var updateResult in totalBatchSummary.UpdateResults)
{
batchResultSummaryText += BuildFileUpdateSummary(updateResult);
}
var emailSuccess = _notificationsApiService.SendEmail(ncoaProcessRequest.EmailSummaryRecipients, _ncoaConfiguration.SummaryEmailSubject, batchResultSummaryText);
batchResultSummaryText += $"Summary Email Request Successful: {emailSuccess}";
Log.Information(batchResultSummaryText);
cleanUpResult.ResponseStack.Add(batchResultSummaryText);
return cleanUpResult;
}
public string CreateTotalBatchSummaryString(NcoaTotalBatchSummary summary, string errorFileLocation = "")
{
return summary.ErrorFileCreated ?
$"NCOA Update Total Batch Summary:<br><br>Total Files in Batch: {summary.UpdateResults.Count}<br><br>Total Records Received: " +
$"{summary.TotalRecordsFound}<br><br>Total Records Updated: {summary.TotalRecordsUpdated}<br><br>Total Error Records: " +
$"{summary.TotalErrorRecords}<br><br>Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}<br><br>" +
$"Error File Created: {summary.ErrorFileCreated}<br><br>Error File Location: {errorFileLocation}<br><br>"
:
$"NCOA Update Total Batch Summary:<br><br>Total Files in Batch: {summary.UpdateResults.Count}<br><br>Total Records Received: " +
$"{summary.TotalRecordsFound}<br><br>Total Records Updated: {summary.TotalRecordsUpdated}<br><br>Total Error Records: " +
$"{summary.TotalErrorRecords}<br><br>Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}<br><br>" +
$"Error File Created: {summary.ErrorFileCreated}<br><br>";
}
public NcoaTotalBatchSummary BuildTotalBatchSummary(List<NcoaUpdateResult> updateResults, bool errorFileCreationSuccess)
{
var totalBatchSummary = new NcoaTotalBatchSummary(updateResults, errorFileCreationSuccess);
foreach(var updateResult in totalBatchSummary.UpdateResults)
{
totalBatchSummary.TotalRecordsFound += updateResult.TotalRecordsFound;
totalBatchSummary.TotalRecordsUpdated += updateResult.UpdateList.Count;
totalBatchSummary.TotalErrorRecords += updateResult.ErrorList.Count;
}
return totalBatchSummary;
}
public string BuildFileUpdateSummary(NcoaUpdateResult updateResult)
{
return $"--------------<br><br>NCOA File In Batch Summary:<br><br>Filename: {updateResult.Filename}" +
$"<br><br>Total Records Received: {updateResult.TotalRecordsFound}<br><br>Total Records Updated: {updateResult.UpdateList.Count}" +
$"<br><br>Total Error Records: {updateResult.ErrorList.Count}<br><br>Total Records Processed: " +
$"{updateResult.UpdateList.Count + updateResult.ErrorList.Count}<br><br>";
}
public async Task<NcoaUpdateResult> HandleFileUpdate(string filename, NcoaUpdateRequest ncoaProcessRequest, FileHelperEngine<NcoaRecord> reader, List<string> exclusionList)
{
var updateResult = new NcoaUpdateResult(filename);
var fileData = await _fileOperationsService.GetContentData($"{ncoaProcessRequest.FinalSourcePath}{filename}");
var ncoaUpdates = reader.ReadString(fileData);
updateResult.TotalRecordsFound = ncoaUpdates.Length;
foreach (var entry in ncoaUpdates)
{
updateResult = await ProcessNcoaRecord(entry, updateResult, ncoaProcessRequest, exclusionList);
}
return updateResult;
}
public async Task<List<string>> GetExclusionList(string filepath)
{
var exclusionList = new List<string>();
try
{
var exclusionListFileData = await _fileOperationsService.GetContentData(filepath);
if (!string.IsNullOrWhiteSpace(exclusionListFileData))
{
exclusionList = exclusionListFileData.Split(_ncoaConfiguration.ExclusionListDelimiter).ToList();
}
return exclusionList;
}
catch (Exception ex)
{
throw new Exception($"Error while trying to retrieve or split ExclusionList. Exception: {ex.Message}");
}
}
public struct NcoaUpdateResult
{
public List<PersonAddrLine> UpdateList { get; set; }
public List<string> ErrorList { get; set; }
public int TotalRecordsFound { get; set; }
public string Filename { get; set; }
public NcoaUpdateResult()
{
ErrorList = new List<string>();
UpdateList = new List<PersonAddrLine>();
TotalRecordsFound = 0;
Filename = null;
}
public NcoaUpdateResult(string filename)
{
ErrorList = new List<string>();
UpdateList = new List<PersonAddrLine>();
TotalRecordsFound = 0;
Filename = filename;
}
public void AddPersonAddrLineToUpdateList(PersonAddrLine entry)
{
UpdateList.Add(entry);
}
public void AddStringToErrorList(NcoaRecord record, string errorMessage, string personNumber = "")
{
var errorRecord = $"{record.ChangeDate}|{record.UserId}|{personNumber}|{record.PrimaryName}|{record.CurrentAddressOne}|" +
$"{record.CurrentAddressTwo}|{record.CurrentAddressThree}|{record.CurrentAddressFour}|{record.CurrentAddressFive}|" +
$"{record.NewAddressLine}|{record.City}|{record.StateCode}|{record.ZipCode}|{record.ZipSuffix.Replace("-", "")}|{errorMessage}\n";
ErrorList.Add(errorRecord);
}
}
public struct NcoaTotalBatchSummary
{
public List<NcoaUpdateResult> UpdateResults { get; set; }
public int TotalRecordsFound { get; set; }
public int TotalRecordsUpdated { get; set; }
public int TotalErrorRecords { get; set; }
public bool ErrorFileCreated { get; set; } = false;
public NcoaTotalBatchSummary(List<NcoaUpdateResult> updateResults, bool errorFileCreationSuccess)
{
UpdateResults = updateResults;
TotalErrorRecords = 0;
TotalRecordsUpdated = 0;
TotalRecordsFound = 0;
ErrorFileCreated = errorFileCreationSuccess;
}
}
}
@@ -0,0 +1,125 @@
using Serilog;
using TimeZoneConverter;
using Newtonsoft.Json;
using LCU.Library.Internal.DataCleanUpModel.Models;
using LCU.Api.Internal.DataCleanUp.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
using LCU.Api.Internal.DataCleanUp.Configuration;
namespace LCU.Api.Internal.DataCleanUp.Services;
public class UpdatePersonForAtmHoldsService : IUpdatePersonForAtmHoldsService
{
private readonly ICoreApiWrapperService _coreApiWrapperService;
private readonly DataCleanupDefaults _dataCleanupDefaults;
private readonly DataCleanUpConfiguration _dataCleanUpConfiguration;
public UpdatePersonForAtmHoldsService(ICoreApiWrapperService coreApiWrapperService, DataCleanupDefaults dataCleanupDefaults, DataCleanUpConfiguration dataCleanUpConfiguration)
{
_coreApiWrapperService = coreApiWrapperService;
_dataCleanupDefaults = dataCleanupDefaults;
_dataCleanUpConfiguration = dataCleanUpConfiguration;
}
public async Task<DataCleanUpResult> CleanUp(DataCleanUpRequest dataCleanUpRequest)
{
Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List<string>());
try
{
var result = JsonConvert.DeserializeObject<UpdatePersonForCheckHoldRequest>(dataCleanUpRequest.DataCleanUpPayload);
var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone);
DateTime? resetStartDate = result.ResetStartDate.HasValue ? TimeZoneInfo.ConvertTime((DateTime)result.ResetStartDate, assumedTimezone) : null;
DateTime? resetEndDate = result.ResetEndDate.HasValue ? TimeZoneInfo.ConvertTime((DateTime)result.ResetEndDate, assumedTimezone) : null;
var personsForUserFieldList = await _coreApiWrapperService.GetAtmCheckHoldsForPersonNumbers(resetStartDate, resetEndDate, result.FetchSize);
ArgumentNullException.ThrowIfNull(personsForUserFieldList);
Log.Information($"Data CleanUp # of Persons {personsForUserFieldList.Count()} at {DateTime.Now}");
foreach (var person in personsForUserFieldList)
{
cleanUpResult = await HandlePersonForCheckHolds(cleanUpResult, person);
}
}
catch (Exception exception)
{
Log.Error(exception, "Error while updating Person for Atm Check Holds.");
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Person for Atm Check Holds. " +
$"Exception:{exception}");
}
Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}");
return cleanUpResult;
}
public async Task<DataCleanUpResult> HandlePersonForCheckHolds(DataCleanUpResult cleanUpResult, PersonCheckHoldsUserField person)
{
try
{
var personNumber = (int)person.PersonNumber;
var response = new PersonUserField();
var personValue = DeterminePersonUserFieldValue(person);
if (person.UserFieldExists)
{
response = await _coreApiWrapperService.UpdateAtmCheckHoldsForPersonNumbers(personNumber, personValue);
}
else
{
response = await _coreApiWrapperService.AddAtmCheckHoldsForPersonNumbers(personNumber, personValue);
}
if (response == null)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Person { person.PersonNumber } for Atm Check Holds.");
}
}
catch(Exception exception)
{
cleanUpResult.Successful = false;
cleanUpResult.ResponseStack.Add($"Error while updating Person { person.PersonNumber } for Atm Check Holds. " +
$"Exception:{exception}");
}
return cleanUpResult;
}
public string DeterminePersonUserFieldValue(PersonCheckHoldsUserField person)
{
string personUserFieldValue = "";
var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone);
DateTime checkHoldEndDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-_dataCleanupDefaults.MemberCheckHoldsDays));
var checkHoldEndDate = TimeZoneInfo.ConvertTime(checkHoldEndDateToConvert, assumedTimezone).Date;
person.OldestActiveEffectiveDate = person.OldestActiveEffectiveDate.HasValue ? person.OldestActiveEffectiveDate.Value.Date : null;
person.RecentClosedEffectiveDate = person.RecentClosedEffectiveDate.HasValue ? person.RecentClosedEffectiveDate.Value.Date : null;
var checkHoldsUserFieldValue = new CheckHoldsUserFieldValue(person, checkHoldEndDate);
foreach (var propertyInfo in checkHoldsUserFieldValue.GetType().GetProperties())
{
if (propertyInfo.PropertyType == typeof(bool))
{
bool value = (bool)propertyInfo.GetValue(checkHoldsUserFieldValue, null);
if (value == true && propertyInfo.Name.Contains("NoValue"))
{
personUserFieldValue = "N";
break;
}
else if (value == true && propertyInfo.Name.Contains("YesValue"))
{
personUserFieldValue = "Y";
break;
};
}
}
return personUserFieldValue;
}
}
@@ -0,0 +1,16 @@
using LCU.Api.Internal.DataCleanUp.Models.ParserModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
namespace LCU.Api.Internal.DataCleanUp.Services.Validation;
public interface INcoaValidationService
{
bool IsBusinessRecord(NcoaRecord record);
int ParsePersonNumber(Agreement agreement);
bool AgreementHasOrgNumber(Agreement agreement);
PersonPostalAddress IsAddrUseCodeFound(IReadOnlyCollection<PersonPostalAddress> addresses, string addrUseCode);
bool IsAddrLineTooLong(string addrLine);
bool IsAddressUpdatedRecently(PersonPostalAddress primaryAddress, int exclusionDays, string currentDateString);
bool IsOnExclusionList(int personNumber, List<string> exclusionList);
}
@@ -0,0 +1,70 @@
using LCU.Api.Internal.DataCleanUp.Models.ParserModels;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses;
namespace LCU.Api.Internal.DataCleanUp.Services.Validation;
public class NcoaValidationService : INcoaValidationService
{
public bool IsBusinessRecord(NcoaRecord record)
{
return !string.IsNullOrWhiteSpace(record.BusinessName);
}
public int ParsePersonNumber(Agreement agreement)
{
int personNumber;
if (agreement == null)
{
return -1;
}
var parseResult = Int32.TryParse(agreement.PersonNumber.ToString(), out personNumber);
if (!parseResult)
{
return -1;
}
return personNumber;
}
public bool AgreementHasOrgNumber(Agreement currentAgreement)
{
return currentAgreement.ByOrgNbr > 0;
}
public PersonPostalAddress IsAddrUseCodeFound(IReadOnlyCollection<PersonPostalAddress> addresses, string addrUseCode)
{
var selectedAddr = addresses.FirstOrDefault(address => addrUseCode.Equals(address.AddressUseCode));
return selectedAddr;
}
public bool IsAddrLineTooLong(string addrLine)
{
return addrLine.Length >= 40;
}
public bool IsAddressUpdatedRecently(PersonPostalAddress primaryAddress, int exclusionDays, string currentDateString)
{
var currentDate = new DateTime();
DateTime.TryParse(currentDateString, out currentDate);
return currentDate.AddDays(exclusionDays).CompareTo(primaryAddress.LastMaintained) < 1;
}
public bool IsOnExclusionList(int personNumber, List<string> exclusionList)
{
foreach (var exclusion in exclusionList)
{
if(exclusion.Equals(personNumber.ToString()))
{
return true;
}
}
return false;
}
}
@@ -0,0 +1,185 @@
using System.Text.Json.Serialization;
using Newtonsoft.Json;
using Microsoft.OpenApi.Models;
using Microsoft.EntityFrameworkCore;
using Serilog;
using MassTransit;
using LCU.Library.Internal.Logging.Models;
using LCU.Library.Internal.Logging;
using LCU.Library.Internal.Logging.Middleware;
using LCU.Api.Internal.DataCleanUp.Services;
using LCU.Api.Internal.DataCleanUp.DataAccess;
using LCU.Library.Internal.LcuMassTransit;
using LCU.Library.Internal.LcuMassTransitModels;
using LCU.Api.Internal.DataCleanUp.Consumers;
using LCU.Api.Internal.DataCleanUpLib.Repositories;
using LCU.Library.Internal.ApiSecurity;
using LCU.Library.Internal.Configuration;
using LCU.Api.Internal.DataCleanUp.Services.Validation;
using LCU.Api.Internal.DataCleanUp.Configuration;
using LCU.Api.Internal.DataCleanUp.Services.Emailers;
using LCU.Api.Internal.DataCleanUpLib.Persistence;
using LCU.Library.Internal.LcuHttpClient;
namespace LCU.Api.Internal.DataCleanUp;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddHttpClient();
services.AddLCUHttpServices();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(Configuration.GetSection("Primary").GetSection("Connections").GetSection("SQL").GetSection("LtvDb").Value);
}, ServiceLifetime.Transient);
var dataCleanUpConfiguration = Configuration.Bind<DataCleanUpConfiguration>(services, "Primary");
Configuration.Bind<CoreApiWrapperConfiguration>(services);
Configuration.Bind<FileOperationsConfiguration>(services);
Configuration.Bind<SavingsMissingRequirementsDefaults>(services);
Configuration.Bind<DataCleanupDefaults>(services);
Configuration.Bind<NcoaConfiguration>(services);
Configuration.Bind<NotificationsApiConfiguration>(services);
Configuration.Bind<FannieMaeConfiguration>(services);
Configuration.Bind<IndirectSavingsRequirementsDefaults>(services);
services.AddApiKeySecurity(Configuration);
var loggerConfiguration = new LoggingConfiguration(dataCleanUpConfiguration.AppName, dataCleanUpConfiguration.SeqApiKey, dataCleanUpConfiguration.SeqUrl);
var lcuLogging = new LcuLogging(loggerConfiguration);
lcuLogging.UseLcuLogging();
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins(
dataCleanUpConfiguration.CorsAllowedOrigins
).AllowAnyHeader().AllowAnyMethod();
});
});
var connectionConfiguration = MassTransitConfigurationSetUp.AddConnectionConfiguration(ref services, Configuration);
//debugging
Console.WriteLine(JsonConvert.SerializeObject(connectionConfiguration));
var receiveEndpointConfiguration = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(Configuration,
"DataCleanUpReceiveEndpoint");
services.AddSingleton(receiveEndpointConfiguration);
//debugging
Console.WriteLine(JsonConvert.SerializeObject(receiveEndpointConfiguration));
AddMassTransitServices(ref services, connectionConfiguration, receiveEndpointConfiguration,dataCleanUpConfiguration);
services.AddScoped<IEnvironmentView, EnvironmentView>();
AddDataCleanUpServices(ref services);
AddDataCleanUpDataAccess(ref services);
services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = $"{dataCleanUpConfiguration.AppName}", Version = "v1" }); });
}
public void AddDataCleanUpServices(ref IServiceCollection services)
{
services.AddScoped<IQueueDataCleanUpService, QueueDataCleanUpService>();
services.AddScoped<IDataCleanUpService, DataCleanUpService>();
services.AddScoped<IHyphenatedUserIdCleanUpService, HyphenatedUserIdCleanUpService>();
services.AddScoped<IDeactivateCustodialEAgreementsService, DeactivateCustodialEAgreementsService>();
services.AddScoped<ICloseCustodialVruAgreementsService, CloseCustodialVruAgreementsService>();
services.AddScoped<IMaskTransactionExternalDescriptionWithSsnService, MaskTransactionExternalDescriptionWithSsnService>();
services.AddScoped<IAddFundsToVipSavingsAccountsService, AddFundsToVipSavingsAccountsService>();
services.AddScoped<IBatchAddFundsToVipSavingsAccountsService, BatchAddFundsToVipSavingsAccountsService>();
services.AddScoped<ICoreApiWrapperService, CoreApiWrapperService>();
services.AddScoped<IUpdateAccountPmiCancelService, UpdateAccountPmiCancelService>();
services.AddScoped<IUpdateAccountNicknameService, UpdateAccountNicknameService>();
services.AddScoped<IUpdateAdminBranchCodesByAccountNumberService, UpdateAdminBranchCodesByAccountNumberService>();
services.AddScoped<IUpdateAccountLoanToValueService, UpdateAccountLoanToValueService>();
services.AddScoped<IUpdateAccountGroupForAnalysisService, UpdateAccountGroupForAnalysisService>();
services.AddScoped<IUpdatePersonForAtmHoldsService, UpdatePersonForAtmHoldsService>();
services.AddScoped<IUpdateMissingBatchSavingsService, UpdateMissingBatchSavingsService>();
services.AddScoped<IUpdateNcoaProcessService, UpdateNcoaProcessService>();
services.AddScoped<IUpdateAccountCreditReportTypeService, UpdateAccountCreditReportTypeService>();
services.AddScoped<IFileOperationsService, FileOperationsService>();
services.AddScoped<IUpdateFannieMaeMortgageService, UpdateFannieMaeMortgageService>();
services.AddScoped<IAddFundsToIndirectSavingsAccountsService, AddFundsToIndirectSavingsAccountsService>();
//Emailers
services.AddScoped<INotificationsApiService, NotificationsApiService>();
//Validation
services.AddScoped<INcoaValidationService, NcoaValidationService>();
//Repository
services.AddScoped<ILtvDataCleanUpRepository, LtvDataCleanUpRepository>();
}
public void AddDataCleanUpDataAccess(ref IServiceCollection services)
{
services.AddScoped<ICoreApiWrapperDao, CoreApiWrapperDao>();
services.AddScoped<IFileOperationsDao, FileOperationsDao>();
services.AddScoped<INotificationsDao, NotificationsDao>();
}
public void AddMassTransitServices(ref IServiceCollection services,
ConnectionConfiguration connectionConfiguration,
ReceiveEndpointConfiguration receiveEndpointConfiguration,
DataCleanUpConfiguration dataCleanUpConfig)
{
services.AddMassTransit(x =>
{
x.AddConsumer<DataCleanUpConsumer>();
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host(connectionConfiguration.HostUrl, "/", host =>
{
host.Username(connectionConfiguration.UserName);
host.Password(connectionConfiguration.Password);
});
if (dataCleanUpConfig.FeatureFlags.RunDataCleanUpConsumer)
{
cfg.ReceiveEndpoint(receiveEndpointConfiguration.ReceiveEndpoint, e =>
{
e.ConfigureConsumer<DataCleanUpConsumer>(context);
e.PrefetchCount = receiveEndpointConfiguration.PrefetchLimit;
e.SetQuorumQueue();
});
}
});
});
services.AddMassTransitHostedService();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "LCU.Api.Internal.DataCleanUp v1"));
app.UseMiddleware<RequestResponseLoggingMiddleware>();
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = RequestResponseLoggingMiddleware.RequestDataParser.EnrichFromRequest;
});
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<style>
#errors {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#errors td, #errors th {
border: 1px solid #ddd;
padding: 8px;
}
#errors tr:nth-child(even) {
background-color: #f2f2f2;
}
#errors th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4CAF50;
color: white;
}
#emailHeader {
color: #0054a2;
}
#errorTableHeader {
background-color: #0054a2;
color: white;
}
</style>
<meta charset="utf-8">
<title>Data Cleanup: Error Monitoring</title>
</head>
<body>
<h1><span id="emailHeader">Data Cleanup: Error Monitoring</span></h1>
<table id="errors">
<thead id="errorTableHeader">
<tr style="height: 17px;">
<td style="max-width: 500px;font-weight: bolder;">Error</td>
</tr>
</thead>
<tbody id="errorRows">
{TableRows}
</tbody>
</table>
</body>
</html>
@@ -0,0 +1,3 @@
<tr id="errorRow" style="height: 22px;">
<td style="max-width: 250px;">{Error}</td>
</tr>
@@ -0,0 +1,187 @@
{
"Primary": {
"AppName": "Data CleanUp Api",
"TimeZone": "America/Chicago",
"SeqUrl": "http://localhost:5080",
"SeqApiKey": "9MQu0vLDwQ1LCFzGixZM",
"CorsAllowedOrigins": [
"http://localhost:3000",
"http://lcu-internal.com",
"https://lcu-internal.com",
"https://qa-api.lcu-internal.com",
"https://uat-api.lcu-internal.com",
"https://api.lcu-internal.com"
],
"Connections": {
"SQL": {
"LtvDb": "data source=bietlq;initial catalog=ETL;Integrated Security=SSPI;MultipleActiveResultSets=True;App=EntityFramework"
}
},
"FeatureFlags": {
"RunDataCleanUpConsumer": true
}
},
"CoreApiWrapperConfiguration": {
"CoreApiTimeout": 120,
"RetryGetAccessChannelPersonIncludes": 3,
"CoreApiWrapperUrl": "http://localhost:44355",
"GetAgreePersonsWithHyphenatedUserId": "/api/core/agreeperson/GetAgreePersonsWithHyphenatedUserId",
"GetActiveCustodialAgreePersonNumbers": "/api/core/agreeperson/GetActiveCustodialAgreePersonNumbers",
"GetActiveCustodialVruCardAgreementAgreePersons": "/api/core/agreeperson/GetActiveCustodialVruCardAgreementAgreePersons",
"GetPersonsForAtmCheckHolds": "/api/core/PersonUserField/GetPersonsForAtmCheckHolds",
"AccessChannelPersons": "/api/core/AccessChannelPersons",
"AccessType": "/api/core/AccessType",
"AccesschannelPersonWithIncludes": "/api/core/AccessChannelPersons/GetWithIncludes",
"PutPersonAgreementDetailTypes": "/api/core/agreeperson/PutPersonAgreementDetailTypes",
"GetTransactionExternalDescriptionsWithSsn": "/api/core/Transaction/GetExternalDescriptionsWithSsn",
"PutTransactionExternalDescription": "/api/core/Transaction/PutExternalDescription",
"PostFundsToAccount": "/api/core/Transaction/PostFundsToAccount",
"GetVipSavingsToFund": "/api/core/Account/GetVipSavingsToFund",
"GetAccountsByMajorMinorBranchAndStatus": "/api/core/Account/GetAccountsByMajorMinorBranchAndStatus",
"GetAdminBranchCodeChangeAccountNumbers": "/api/core/Account/GetAdminBranchCodeChangeAccountNumbers",
"GetAccountsForGroupAnalysis": "/api/core/Account/GetAccountsForGroupAnalysis",
"PutAccountBranchCode": "/api/core/Account/PutAccountBranchCode",
"PutAccountLoanToValue": "/api/core/Account/PutAccountLoanToValue",
"PutAccountAnalysisGroup": "/api/core/Account/PutAccountAnalysisGroup",
"PutPersonUserFieldForAtmCheckHolds": "/api/core/PersonUserField/PutPersonUserFieldForAtmCheckHolds",
"PostPersonUserFieldForAtmCheckHolds": "/api/core/PersonUserField/PostPersonUserFieldForAtmCheckHolds",
"PostOrganizationAccount": "/api/core/Account/PostOrganizationAccount",
"PostPersonAccount": "/api/core/Account/PostPersonAccount",
"PutOrganizationMaintenanceRequest": "/api/core/Account/PutOrganizationMaintenanceRequest",
"PutAccountNickNameUpdateRequest": "/api/core/Account/PutAccountNickNameUpdateRequest",
"GetAgreementByUserId": "/api/core/Agree/AgreementByUserId/{userId}",
"GetPersonPostalAddressByPersonNumber": "/api/core/Address/GetByPersonNumber",
"PutAddrLineByPersonNumber": "/api/core/Address/UpdatePersonAddrLine",
"PutAccountCreditReportType": "/api/core/Account/PutAccountCreditReportType",
"GetPropertyNumberByAccountNumber": "/api/core/Loan/GetPropertyInformation",
"GetAccountByAccountNumber": "/api/core/Account/GetAccountByAccountNumber",
"PropertyUserField": "/api/core/PropertyUserField",
"PostPropertyUserField": "/api/core/PropertyUserField/PostPropertyUserField",
"PutPropertyUserField": "/api/core/PropertyUserField/PutPropertyUserField",
"PutPersonUserField": "/api/core/PersonUserField/PutPersonUserField",
"PostPersonUserField": "/api/core/PersonUserField/PostPersonUserField",
"PersonUserField": "/api/core/PersonUserField",
"AccountUserField": "/api/core/AccountUserField"
},
"FileOperationsConfiguration": {
"FileOperationsUrl": "https://qa-fileoperationsapi.lcu-internal.com",
"GetFile": "/api/FileOperations/",
"WriteFile": "/api/FileOperations/WriteFileData",
"BuildDynamicFileList": "/DynamicFile/BuildDynamicFileList"
},
"ConnectionConfiguration": {
"HostUrl": "localhost",
"UserName": "guest",
"Password": "guest"
},
"DataCleanUpReceiveEndpoint": {
"ReceiveEndpoint": "LCU.DataCleanUp",
"ReceiveEndpointType": "exchange",
"PrefetchLimit": 1
},
"SavingsMissingRequirementsDefaults": {
"SavingDefaults": {
"AccountDescription": "VIP SAVINGS",
"BatchAccountDescription": "SV01",
"BankOrganizationNumber": 1,
"CurrentMinorAccountTypeCode": "SV01",
"DeliveryMethodCode": "PRNT",
"MajorAccountTypeCode": "SAV",
"OwnershipCode": "S",
"IsTaxReportedForOwner": true,
"IsTaxReportedForSigner": true,
"IsValid": true,
"CurrentAccountStatusCode": "APPR"
},
"FundsToAccountDefaults": {
"Description": "Opening Deposit",
"GLAccountNumber": 19619869597,
"TransactionTypeCodeGL": "GLD",
"TransactionTypeCodeDeposit": "DEP",
"FundsDefaults": {
"ClearingCategoryCode": "IMED",
"FundAmount": 5.00,
"FundTypeCode": "EL",
"FundTypeDetailCode": "INTR"
}
}
},
"IndirectSavingsRequirementsDefaults": {
"Description": "Opening Deposit",
"GLAccountNumber": 19617806783,
"TransactionTypeCodeGL": "GLD",
"TransactionTypeCodeDeposit": "DEP",
"FundsDefaults": {
"ClearingCategoryCode": "IMED",
"FundAmount": 5.00,
"FundTypeCode": "EL",
"FundTypeDetailCode": "INTR"
},
"FundingCoreRequests": {
"MajorAccountTypes": [ "SAV" ],
"MinorAccountTypes": [ "SV01", "BS01" ],
"BranchCodeTypes": [ "1310" ],
"AccountStatusTypes": [ "APPR" ]
}
},
"DataCleanUpDefaults": {
"DigitalBankingBranchCode": "1210",
"MemberCheckHoldsUserFieldCode": "MBRH",
"MemberCheckHoldsDays": 29,
"BatchAddFunds": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv",
"BatchAddFundsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\",
"BatchSavingsSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv",
"BatchSavingsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\",
"AccountNicknameSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\Nickname update.csv",
"PmiCancelSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\PMI Cancel.csv",
"PmiCancelSummaryPath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\",
"LtvExcludedMinorAccountTypes": [
"DL01",
"DL02",
"DL03",
"DL04",
"DL05",
"DL06",
"DL07",
"DL08",
"DL09",
"DL10",
"DL11",
"DL12",
"DL13",
"DL14",
"DL15",
"DL16"
]
},
"NcoaConfiguration": {
"PrimaryAddressLabel": "PRI",
"StreetTypeLabel": "ST",
"UrlBase": "/Persons/{personNumber}/PostalAddresses/PRI",
"UsaLabel": "USA",
"PoBoxLabel": "PO BOX",
"PoBoxAddressTypeLabel": "POBN",
"ErrorFileDefaultName": "NCOAErrorRecord",
"PersonNumberLabel": "{personNumber}",
"SummaryEmailSubject": "NCOA Process Summary Email",
"ExclusionListDelimiter": "|"
},
"FannieMaeConfiguration": {
"ErrorFileDefaultName": "FannieMaeErrorRecord",
"SummaryEmailSubject": "Fannie Mae Mortgage Summary Email",
"FileDateFormat": "M/d/yyyy",
"DnaDateFormat": "yyyy-MM-dd",
"PoolDateUserFieldId": "PLDT",
"PoolNbrUserFieldId": "PLNB"
},
"NotificationsApiConfiguration": {
"EmailEndpoint": "https://qa-notifications-api.apps.azure.lcu-internal.com/api/Email"
},
"ApiSecurityConfiguration": {
"ApiKeyAuthenticationFailureBehavior": "Error",
"InternalApiKeySet": {
"DataCleanUp": "772e2926-78b5-4884-88da-73e2c23fad71"
},
"ExternalApiKeySet": {}
}
}
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Linq;
using LCU.Library.Internal.DataCleanUpModel.Entities;
namespace LCU.Api.Internal.DataCleanUpLib.Extensions
{
public static class QueryableExcludeMinorAccountType
{
public static IQueryable<Ltv_DataCleanUp> ExcludeMinorAccountType(this IQueryable<Ltv_DataCleanUp> queryable, List<string> listExcludedMinorAccountTypes)
{
if (listExcludedMinorAccountTypes == null || !listExcludedMinorAccountTypes.Any())
{
return queryable;
}
return queryable.Where(ltv_DataCleanUp => !listExcludedMinorAccountTypes.Contains(ltv_DataCleanUp.MinorType));
}
}
}
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="LCU.Library.Internal.CoreApiWrapperModel" Version="2.27.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.17" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LCU.Library.Internal.DataCleanUpModel\LCU.Library.Internal.DataCleanUpModel.csproj" />
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More