using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using LCU.API.Collections.RepoApi.Exceptions; using LCU.API.Collections.RepoApi.Models; using LCU.Shared.Collections.RepoApiLib.Exceptions; using LCU.Shared.Collections.RepoApiLib.Models; using LCU.Shared.Collections.RepoApiLib.Repositories; using Serilog; namespace LCU.API.Collections.RepoApi.Services { public class EventAlertService : IEventAlertService { private readonly IEventAlertRepository _eventAlertRepository; private readonly IUnitOfWork _unitOfWork; private const string RedeemedStatus = "REDEEMED"; private const string CancelledStatus = "RECA"; private readonly IRepoAccountRepository _accountRepository; public EventAlertService( IEventAlertRepository eventAlertRepository, IUnitOfWork unitOfWork, IRepoAccountRepository accountRepository) { _eventAlertRepository = eventAlertRepository; _unitOfWork = unitOfWork; _accountRepository = accountRepository; } public async Task> ListAll() { try { return await _eventAlertRepository.ListAllAsync(); } catch (Exception ex) { Log.Error(ex, "Failure retrieving All Event Alerts"); throw new ServerErrorException(); } } public async Task> ListUnread() { try { return await _eventAlertRepository.ListUnreadAsync(); } catch (Exception ex) { Log.Error(ex, "Failure retrieving Unread Event Alerts"); throw new ServerErrorException(); } } public async Task> ListWithinDateRange(DateTime start, DateTime end) { try { return await _eventAlertRepository.ListWithinDateRangeAsync(start, end); } catch (Exception ex) { Log.Error(ex, $"Failure retrieving Event Alerts between {start} and {end}"); throw new ServerErrorException(); } } public async Task> ListActionNeeded() { try { var repoNoAuction = await _eventAlertRepository.ListRepoNoAuctionAsync(); var repoNoCompany = await _eventAlertRepository.ListRepoNoCompanyAsync(); var o4rNoCompany = await _eventAlertRepository.ListO4rNoCompanyAsync(); var retitle = await _eventAlertRepository.ListReadyForRetitleAsync(); var floorUpdateFail = await _eventAlertRepository.ListFloorUpdateFailedAsync(); var setFloor = await _eventAlertRepository.ListFloorNeedsSettingAsync(); return repoNoAuction.Concat(repoNoCompany).Concat(o4rNoCompany).Concat(retitle).Concat(floorUpdateFail).Concat(setFloor).ToList(); } catch (Exception ex) { Log.Error(ex, "Failure retrieving Action Needed Event Alerts"); throw new ServerErrorException(); } } public async Task SaveAsync(EventAlert eventAlert) { try { if (IsStatusCancelledOrRedeemed(eventAlert.RepoId.Value).Result) { throw new UnwantedStatusException(eventAlert.RepoId.Value, eventAlert.AccountNo); } await _eventAlertRepository.AddAsync(eventAlert); await _unitOfWork.CompleteAsync(); return eventAlert; } catch (DuplicateResourceException ex) { Log.Debug(ex, $"SaveAsync: Valid Alert Already Exists eventAlert:{eventAlert}", eventAlert); throw ex; } catch(UnwantedStatusException ex) { Log.Error(ex, $"SaveAsync: Status of Repo is Redeemed or Cancelled. Event Alert: {eventAlert} not created", eventAlert); throw; } catch (Exception ex) { Log.Error(ex, $"SaveAsync: Failure saving Event Alert: {eventAlert}", eventAlert); throw new ServerErrorException(); } } public async Task> SaveRangeAsync(List eventAlerts) { IEnumerable addedEventAlerts = new List(); try { addedEventAlerts = await _eventAlertRepository.AddRangeAsync(eventAlerts); await _unitOfWork.CompleteAsync(); } catch (Exception ex) { Log.Error(ex, $"EventAlertService: Failure Saving Range Of Event Alerts: {eventAlerts}", eventAlerts); } return addedEventAlerts; } public async Task Get(int id) { EventAlert eventAlert; try { eventAlert = await _eventAlertRepository.FindByIdAsync(id); await _unitOfWork.CompleteAsync(); } catch (Exception ex) { Log.Error(ex, $"Failure retrieving Event Alert with id: {id}"); throw new ServerErrorException(); } if (eventAlert == null) { throw new NotFoundException($"EventAlert with id {id} not found."); } return eventAlert; } public async Task UpdateAsync(EventAlert eventAlert, AppUser user) { EventAlert existingEventAlert = null; try { existingEventAlert = await _eventAlertRepository.FindByIdAsync(eventAlert.Id); } catch(Exception ex) { Log.Error(ex, $"Failed to find existing event alert with Id: {eventAlert.Id}, user: {user}", eventAlert, user); throw new ServerErrorException(); } if (existingEventAlert == null) { throw new NotFoundException($"EventAlert with id {eventAlert.Id} not found."); } existingEventAlert.Message = eventAlert.Message; existingEventAlert.SubMessage = eventAlert.SubMessage; if (existingEventAlert.DateMarkedRead == null && eventAlert.DateMarkedRead != null) { existingEventAlert.MarkedReadBy = user.FirstName + " " + user.LastName; existingEventAlert.DateMarkedRead = eventAlert.DateMarkedRead; } try { _eventAlertRepository.Update(existingEventAlert); await _unitOfWork.CompleteAsync(); return (existingEventAlert); } catch (SqlException ex) { Log.Error(ex, $"SQL Failure updating Event Alert: {eventAlert}", eventAlert); throw new ServerErrorException(); } catch (Exception ex) { Log.Error(ex, $"Failure updating Event Alert {eventAlert}", eventAlert); throw new ServerErrorException(); } } public async Task DeleteAsync(int id) { EventAlert existingEventAlert = null; try { existingEventAlert = await _eventAlertRepository.FindByIdAsync(id); } catch(Exception ex) { Log.Error(ex, $"Failed to find existing event alert with Id: {id}."); throw new ServerErrorException(); } if (existingEventAlert == null) { throw new NotFoundException($"EventAlert with id {id} not found."); } try { _eventAlertRepository.Remove(existingEventAlert); await _unitOfWork.CompleteAsync(); return existingEventAlert; } catch (SqlException ex) { Log.Error(ex, $"SQL Failure deleting Event Alert with id {id}"); throw new ServerErrorException(); } catch (Exception ex) { Log.Error(ex, $"Failure deleting Event Alert with id {id}"); throw new ServerErrorException(); } } public async Task> MarkAllAsRead(string accountNo) { IEnumerable existingEventAlerts = null; try { existingEventAlerts = await _eventAlertRepository.ListUnreadByAccountNoAsync(accountNo); } catch (Exception ex) { Log.Error(ex, $"Failed to find existing event alerts with accountNo: {accountNo}"); throw new ServerErrorException(); } if (existingEventAlerts == null) { throw new NotFoundException($"EventAlerts for accountNo: {accountNo} not found."); } var ret = new List(); foreach (EventAlert eventAlert in existingEventAlerts) { eventAlert.MarkedReadBy = "System"; eventAlert.DateMarkedRead = DateTime.Now; try { _eventAlertRepository.Update(eventAlert); ret.Add(eventAlert); } catch (SqlException ex) { Log.Error(ex, $"SQL Failure updating Event Alert: {eventAlert} in the list {existingEventAlerts}. Will not commit any changes.", eventAlert); throw new ServerErrorException(); } catch (Exception ex) { Log.Error(ex, $"Failure updating Event Alert {eventAlert} in the list {existingEventAlerts}. Will not commit any changes", eventAlert); throw new ServerErrorException(); } } await _unitOfWork.CompleteAsync(); return ret; } private async Task IsStatusCancelledOrRedeemed(int repoId) { var repo = await _accountRepository.FindByIdAsync(repoId); if (repo == null) { return false; } return repo.Status.Equals(CancelledStatus) || repo.Status.Equals(RedeemedStatus); } } }