using System.Globalization; using System.IO; using CsvHelper; using CsvHelper.Configuration; using LCU.API.Internal.Operations.IncentiveApi.Models.Action; using LCU.API.Internal.Operations.IncentiveApiLib.Repositories; using LCU.Library.Internal.IncentiveApiModels.Entities; using LCU.Library.Internal.IncentiveApiModels.Enums; using LCU.API.Internal.Operations.IncentiveApi.Services.MicroApiServices; using LCU.Library.Internal.IncentiveApiModels.Requests; using LCU.API.Internal.Operations.IncentiveApi.Services; using LCU.API.Internal.Operations.IncentiveApi.Services.Transformations; using LCU.Library.Internal.ApiResponse.Services; using LCU.Library.Internal.IncentiveApiModels.Results; namespace LCU.API.Internal.Operations.IncentiveApi.Services.Action; public class ActionCreditCardImportService : IActionCreditCardImportService { private readonly IUserRepository _userRepository; private readonly IActivityService _activityService; private readonly IDeadActivityService _deadActivityService; private readonly IFileOperationsApiService _fileOperationsApiService; private readonly ProcessResult _actionCreditCardResult; public ActionCreditCardImportService(IUserRepository userRepository, IFileOperationsApiService fileOperationsApiService, IActivityService activityService, IDeadActivityService deadActivityService) { _userRepository = userRepository; _fileOperationsApiService = fileOperationsApiService; _activityService = activityService; _deadActivityService = deadActivityService; _actionCreditCardResult = new ProcessResult(); } public async Task RunActionCreditCardProcess(ActionCreditCardRequest request) { try { var importedPersonal = await ImportTransactions("personal", request); Log.Information($"Imported {importedPersonal.Count} credit cards - personal."); var importedBusiness = await ImportTransactions("business", request); Log.Information($"Imported {importedBusiness.Count} credit cards - business."); _actionCreditCardResult.MessageStack.Add($"Imported {importedPersonal.Count()} personal and {importedBusiness.Count()} business credit cards."); await SafeQueueReturnResponse.TryQueueResponse(request, _actionCreditCardResult.Success, _actionCreditCardResult.MessageStack, nameof(ActionCreditCardImportService)); } catch (Exception exception) { var message = $"There was an issue with handling Import Action Credit Card Sales Exception Message: {exception.Message}."; _actionCreditCardResult.MessageStack.Add(message); _actionCreditCardResult.Success = false; await SafeQueueReturnResponse.TryQueueResponse(request, _actionCreditCardResult.Success, _actionCreditCardResult.MessageStack, nameof(ActionCreditCardImportService)); } } public async Task> ImportTransactions(string fileIdentifier, ActionCreditCardRequest request) where T : IActionFileObject { var dynamicFileListRequest = request.ToDynamicActionCreditCardFileListRequest(); var files = await _fileOperationsApiService.BuildDynamicFileList(dynamicFileListRequest); var activity = new List(); foreach (var fileName in files) { var stringContent = _fileOperationsApiService.GetFileContent($"{request.FinalBasePath}{fileName}"); using var stringReader = new StringReader(stringContent.Result); var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", HasHeaderRecord = true, HeaderValidated = null, MissingFieldFound = null, IgnoreBlankLines = true }; using var csv = new CsvReader(stringReader, config); var records = csv.GetRecords().ToList(); var allActivity = await CreateActivity(records); await _activityService.SaveActivityRangeAsync(allActivity); activity.AddRange(allActivity); } return activity; } public async Task> CreateActivity(IEnumerable transactions) where T : IActionFileObject { var activities = new List(); var deadActivities = new List(); foreach (var actionSaleRow in transactions) { var email = actionSaleRow.GetEmployeeEmail(); var employee = string.IsNullOrEmpty(email) ? null : await FindEmployee(email); if (employee == null) { email = actionSaleRow.GetLoanOfficerEmail(); employee = string.IsNullOrEmpty(email) ? null : await FindEmployee(email); } if (employee == null) { email = actionSaleRow.GetLoanOfficerEmailByName(); employee = string.IsNullOrEmpty(email) ? null : await FindEmployee(email); } if(employee == null){ Log.Warning($"Action Import, No user for {email}. Saving as Dead Activity."); deadActivities.Add(actionSaleRow.CreateDeadActivity(DeadActivityReason.MissingRequiredField, $"Action Import, No user for {email}", email)); continue; } var homeDept = employee.FindHomeDepartment(); if (homeDept == null) { Log.Warning($"User has no reliably determinable home department, {employee.EmployeeId}. Saving as Dead Activity."); deadActivities.Add( actionSaleRow.CreateDeadActivity(DeadActivityReason.MissingRequiredField, $"User has no reliably determinable home department, {employee.EmployeeId}", email, employee.EmployeeId)); continue; } var activity = actionSaleRow.CreateActivity(employee); if (activities.Any(x => x.SourceId == activity.SourceId)) { Log.Fatal( $"Duplicate activity in credit card file for Incentive Manager, sourceId is {activity.SourceId}"); continue; } activities.Add(activity); } try { await _deadActivityService.SaveDeadActivityRange(deadActivities); } catch (Exception ex) { Log.Error(ex, "Failed to save dead activities from ActionCreditCardImportService. Dead Activities will be lost."); } return activities; } private async Task FindEmployee(string employeeEmail) { try { return await _userRepository.FindUserByAdEmailAsync(employeeEmail); } catch(Exception ex) { Log.Warning(ex, "Error when finding user by email in ActionCreditCardImportService."); return null; } } }