using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; using ReserveManagementSystemApi.Mappers; using ReserveManagementSystemApi.Helpers; using ReserveManagementSystemApi.Models; using ReserveManagementSystemApi.ServiceClients; using ReserveManagementSystemLib.Models; using ReserveManagementSystemLib.Repositories; using ReserveManagementSystemLib.Configuration; namespace ReserveManagementSystemApi.Services { public class ExportService: IExportService { private readonly ILoanRepository _loanRepository; private readonly ICoreApiServiceClient _coreApiServiceClient; private readonly IMinorAccountTypeRepository _minorAccountTypeRepository; private readonly RmsApiConfiguration _rmsApiConfig; public ExportService(ILoanRepository loanRepository, ICoreApiServiceClient coreApiServiceClient, IMinorAccountTypeRepository minorAccountTypeRepository, RmsApiConfiguration rmsApiConfig) { _loanRepository = loanRepository; _coreApiServiceClient = coreApiServiceClient; _minorAccountTypeRepository = minorAccountTypeRepository; _rmsApiConfig = rmsApiConfig; } public async Task ExportReservesAsync(DateTime currentDate) { var numberOfLoansUpdated = 0; try { var loansToUpdate = await _loanRepository.GetAll().Where(l => l.ExportedReserveDate == null).ToListAsync(); var groupedLoanRequests = loansToUpdate.Select(ExportMapper.MapLoanToIndirectLoanForReserve).ToList(); var exportResult = await SendBatchListMonetaryTransactionRequests(groupedLoanRequests); if (exportResult != null || exportResult.Any()) { var loansExported = new List(); loansToUpdate.ForEach(loan => { var validLoan = exportResult.Where(e => e.AccountNumber.ToString() == loan.LoanNumber).FirstOrDefault(); if (validLoan != null && validLoan.WasSuccessful) { loan.ExportedReserveDate = currentDate; numberOfLoansUpdated += 1; loan.Adjustment = 0; loansExported.Add(loan); //update successful loan export with exported date } else { Log.Error($"Failure to export loan reserve account number: {loan.LoanNumber}"); } }); await _loanRepository.UpdateAsync(loansExported); Log.Information($"Exported {numberOfLoansUpdated} reserves"); } } catch (Exception ex) { Log.Error(ex, "Failure exporting loan reserves."); throw; } return numberOfLoansUpdated; } public async Task ExportChargebacksAsync(DateTime currentDate) { var numberOfLoansUpdated = 0; try { var loansToUpdate = await _loanRepository.GetAll().Where(l => l.ExportedChargebackDate == null && l.PaidLoanDate != null).ToListAsync(); var groupedLoanRequests = new List(); loansToUpdate.ForEach(loan => { var accountType = GetMinorAccountType(loan.AccountType); groupedLoanRequests.Add(ExportMapper.MapLoanToIndirectLoanForChargeback(loan, accountType)); } ); var exportResult = await SendBatchListMonetaryTransactionRequests(groupedLoanRequests); if (exportResult != null || exportResult.Any()) { var loansExported = new List(); loansToUpdate.ForEach(loan => { var accountType = GetMinorAccountType(loan.AccountType); var validLoan = exportResult.Where(e => e.AccountNumber.ToString() == accountType.GeneralLedgerAccountNumber).FirstOrDefault(); if (validLoan != null && validLoan.WasSuccessful) { loan.ExportedChargebackDate = currentDate; numberOfLoansUpdated += 1; loan.Adjustment = 0; loansExported.Add(loan); //update successful loan export with exported date } else { Log.Error($"Failure to export loan reserve account number: {loan.LoanNumber}"); } }); await _loanRepository.UpdateAsync(loansExported); Log.Information($"Exported {numberOfLoansUpdated} chargebacks"); } else { Log.Error("Failure exporting loan chargebacks."); } } catch (Exception ex) { Log.Error(ex, "Failure exporting loan chargebacks."); throw; } return numberOfLoansUpdated; } public async Task> ExportBoatLoansAsync(List loans) { var loansExported = new List(); try { var reserveLoans = loans.Where(l => l.ReserveAmount != 0); if (reserveLoans != null || reserveLoans.Any()) { var groupedReserveRequests = reserveLoans.Select(ExportMapper.MapLoanToIndirectLoanForReserve).ToList(); var exportReserveResult = await SendBatchListMonetaryTransactionRequests(groupedReserveRequests); loansExported.AddRange(MapBoatExportResults(exportReserveResult, reserveLoans.ToList())); } var chargebackLoans = loans.Where(l => l.ChargeBack != 0).ToList(); if (chargebackLoans != null || chargebackLoans.Any()) { var groupedLoanRequests = new List(); chargebackLoans.ForEach(loan => { var accountType = GetMinorAccountType(loan.AccountType); groupedLoanRequests.Add(ExportMapper.MapLoanToIndirectLoanForChargeback(loan, accountType)); } ); var exportResult = await _coreApiServiceClient.PostMonetaryTransactions(groupedLoanRequests); loansExported.AddRange(MapBoatExportResults(exportResult, chargebackLoans.ToList())); } } catch (Exception ex) { Log.Error(ex, "Failure exporting boat loans."); throw; } return loansExported; } public async Task MarkReservesAsExportedAsync(List loans, DateTime currentDate) { try { loans.ForEach(l => { l.ExportedReserveDate = currentDate; }); await _loanRepository.UpdateAsync(loans); Log.Information($"Marked {loans.Count} loan reserves as exported (without exporting)"); } catch (Exception ex) { Log.Error(ex, "Failure marking loan reserves as exported."); throw; } return loans.Count; } public async Task MarkReservesAndChargebacksAsExportedAsync(List loans, DateTime currentDate) { try { loans.ForEach(l => { l.ExportedReserveDate = currentDate; l.ExportedChargebackDate = currentDate; }); await _loanRepository.UpdateAsync(loans); Log.Information($"Marked {loans.Count} loan reserves and chargebacks as exported (without exporting)"); } catch (Exception ex) { Log.Error(ex, "Failure marking loan reserves and chargebacks as exported."); throw; } return loans.Count; } private List MapBoatExportResults(List exportResult, List loansToUpdate) { var numberOfLoansUpdated = 0; var loansExported = new List(); if (exportResult != null || exportResult.Any()) { loansToUpdate.ForEach(loan => { var boatLoan = new ImportBoatLoan(); string acccountNumber; if (loan.ReserveAmount != 0) { acccountNumber = loan.LoanNumber; } else { var accountType = GetMinorAccountType(loan.AccountType); acccountNumber = accountType.GeneralLedgerAccountNumber; } var validLoan = exportResult.Where(e => e.AccountNumber.ToString() == acccountNumber).Any(); var validDealer = exportResult.Where(e => e.AccountNumber.ToString() == loan.Dealer.DealerAccountNumber).Any(); if (validLoan && validDealer) { numberOfLoansUpdated += 1; boatLoan.LoanNumber = loan.LoanNumber; boatLoan.WasSuccessful = true; } else { var error = $"Failure to export boat loan account number: {loan.LoanNumber}"; boatLoan.LoanNumber = loan.LoanNumber; boatLoan.WasSuccessful = false; boatLoan.ErrorMessage = error; Log.Error(error); } loansExported.Add(boatLoan); }); Log.Information($"Exported {numberOfLoansUpdated} boat loans"); } return loansExported; } private MinorAccountType GetMinorAccountType(string loanAccountType) { var result = _minorAccountTypeRepository.GetMinorAccountType(loanAccountType); return result; } public async Task> SendBatchListMonetaryTransactionRequests(List groupedLoanRequests) { var result = new List(); var batchSize = _rmsApiConfig.DefaultBatchSize; foreach (var batch in BatchHelper.CreateBatch(groupedLoanRequests, batchSize)) { var response = await _coreApiServiceClient.PostMonetaryTransactions(batch.ToList()); result.AddRange(response); }; return result; } } }