protected bool ShouldNotifyInsuranceUsers(CostNotificationUsers costUsers) { var costOwner = costUsers.CostOwner; var agency = costOwner.Agency; return(costUsers.InsuranceUsers?.Count > 0 && (agency.IsEuropeanAgency(RegionsService) || agency.IsNorthAmericanAgency(RegionsService))); }
private async Task BuildAutoApprovedNotification(CostNotificationUsers costUsers, Cost cost, CostStageRevision latestRevision, List <EmailNotificationMessage <CostNotificationObject> > notifications) { var approver = await GetLastApprover(cost); notifications.AddRange(await _emailNotificationBuilder.BuildCostApprovedNotification(costUsers, cost, latestRevision, approver, core.Constants.EmailApprovalType.Brand, DateTime.UtcNow)); }
internal async Task<IEnumerable<EmailNotificationMessage<CostNotificationObject>>> Build(Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List<EmailNotificationMessage<CostNotificationObject>>(); //Cost Owner var costOwner = costUsers.CostOwner; var recipients = new List<string> { costOwner.GdamUserId }; recipients.AddRange(costUsers.Watchers); var costOwnerNotification = new EmailNotificationMessage<CostNotificationObject>(Constants.EmailNotificationActionType.Cancelled, recipients); AddSharedTo(costOwnerNotification); MapEmailNotificationObject(costOwnerNotification.Object, cost, costOwner); PopulateOtherFields(costOwnerNotification, Constants.EmailNotificationParents.CostOwner, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(costOwnerNotification.Object, cost.Id); notifications.Add(costOwnerNotification); if (ShouldNotifyInsuranceUsers(costUsers)) { var insuranceUserNotification = new EmailNotificationMessage<CostNotificationObject>(Constants.EmailNotificationActionType.Cancelled, costUsers.InsuranceUsers); AddSharedTo(insuranceUserNotification); MapEmailNotificationObject(insuranceUserNotification.Object, cost, costOwner); PopulateOtherFields(insuranceUserNotification, Constants.EmailNotificationParents.InsuranceUser, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(insuranceUserNotification.Object, cost.Id); notifications.Add(insuranceUserNotification); } await AddFinanceManagerNotification(Constants.EmailNotificationActionType.Cancelled, cost, costUsers, costStageRevision, timestamp, notifications); return notifications; }
public async Task <bool> CostHasBeenRequestedToBeReopened(Guid costId, Guid userId, Guid userModuleId) { if (costId == Guid.Empty) { return(false); } if (userId == Guid.Empty) { return(false); } var cost = await _efContext.Cost .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .Include(c => c.Project) .ThenInclude(p => p.Brand) .IncludeCostOwner() .FirstOrDefaultAsync(c => c.Id == costId); var costStageRevision = cost.LatestCostStageRevision; var adminUsers = await _efContext.CostUser.Include(x => x.UserUserGroups).ThenInclude(x => x.UserGroup) .Where(u => u.UserUserGroups.Any(x => x.UserGroup.Role.Name == Roles.ClientAdmin && x.UserGroup.ObjectId == userModuleId)).ToListAsync(); var requestedBy = await _efContext.CostUser.FindAsync(userId); var costOwner = cost.Owner; var financeManagementUsers = await _costUserService.GetFinanceManagementUsers(cost.UserGroups, Constants.BudgetRegion.NorthAmerica); var insuranceUsers = await _costUserService.GetInsuranceUsers(costOwner.Agency); var costUsers = new CostNotificationUsers { CostOwner = costOwner, FinanceManagementUsers = financeManagementUsers, InsuranceUsers = insuranceUsers, Watchers = await GetWatchers(costId), ClientAdmins = adminUsers }; var notificationMessages = await _emailNotificationBuilder.BuildCostReopenRequestedNotification( costUsers, cost, costStageRevision, DateTime.UtcNow, requestedBy); bool sent = false; foreach (var message in notificationMessages) { sent = await _paperPusherClient.SendMessage(message); } //For Brand Approval, cancel the reminder, if any await _reminderService.CancelReminder(cost.Id); return(sent); }
protected void MapEmailNotificationObject(CostNotificationObject obj, Cost cost, CostUser costOwner, CostUser costApprover = null) { var users = new CostNotificationUsers { CostOwner = costOwner, Approver = costApprover }; MapEmailNotificationObject(obj, cost, users); }
public async Task <bool> CostHasBeenRecalled(Guid costId, Guid userId) { if (costId == Guid.Empty) { return(false); } if (userId == Guid.Empty) { return(false); } var cost = await _efContext.Cost .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .Include(c => c.Project) .ThenInclude(p => p.Brand) .IncludeCostOwner() .FirstOrDefaultAsync(c => c.Id == costId); var costStageRevision = cost.LatestCostStageRevision; var recaller = await _efContext.CostUser.FirstOrDefaultAsync(u => u.Id == userId); var costOwner = cost.Owner; var insuranceUsers = await _costUserService.GetInsuranceUsers(costOwner.Agency); var financeManagementUsers = await _costUserService.GetFinanceManagementUsers(cost.UserGroups, Constants.BudgetRegion.NorthAmerica); var costUsers = new CostNotificationUsers { CostOwner = cost.Owner, InsuranceUsers = insuranceUsers, FinanceManagementUsers = financeManagementUsers }; var notificationMessages = await _emailNotificationBuilder.BuildCostRecalledNotification( costUsers, cost, costStageRevision, recaller, DateTime.UtcNow); bool sent = false; foreach (var message in notificationMessages) { sent = await _paperPusherClient.SendMessage(message); } //For Brand Approval, cancel the reminder, if any await _reminderService.CancelReminder(cost.Id); return(sent); }
public async Task <bool> CostHasBeenCancelled(Guid costId) { if (costId == Guid.Empty) { return(false); } var cost = await _efContext.Cost .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .Include(c => c.Project) .ThenInclude(p => p.Brand) .IncludeCostOwner() .FirstOrDefaultAsync(c => c.Id == costId); if (cost.Status != CostStageRevisionStatus.Cancelled) { // Cost.Status might be PendingCancellation so don't send an email until // the Cancellation message has been sent from Coupa to Costs via AMQ. return(false); } var costStageRevision = cost.LatestCostStageRevision; var costOwner = cost.Owner; var insuranceUsers = await _costUserService.GetInsuranceUsers(costOwner.Agency); var financeManagementUsers = await _costUserService.GetFinanceManagementUsers(cost.UserGroups, Constants.BudgetRegion.NorthAmerica); var costUsers = new CostNotificationUsers { CostOwner = costOwner, InsuranceUsers = insuranceUsers, Watchers = await GetWatchers(costId), FinanceManagementUsers = financeManagementUsers }; var notificationMessages = await _emailNotificationBuilder.BuildCostCancelledNotification(costUsers, cost, costStageRevision, DateTime.UtcNow); bool sent = false; foreach (var message in notificationMessages) { sent = await _paperPusherClient.SendMessage(message); } return(sent); }
public async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > BuildCostReopenRequestedNotification( CostNotificationUsers costUsers, Cost cost, CostStageRevision costStageRevision, DateTime timestamp, CostUser requestedBy ) { if (cost == null) { Logger.Error("Failed to create an email notification because cost is null."); throw new ArgumentNullException(nameof(cost)); } if (costStageRevision == null) { Logger.Error("Failed to create an email notification because costStageRevision is null."); throw new ArgumentNullException(nameof(costStageRevision)); } if (costUsers.ClientAdmins == null || !costUsers.ClientAdmins.Any()) { Logger.Error("Failed to create an email notification because costUsers is null or empty."); throw new ArgumentNullException(nameof(costUsers.ClientAdmins)); } if (requestedBy == null) { Logger.Error("Failed to create an email notification because rejectedBy is null."); throw new ArgumentNullException(nameof(requestedBy)); } if (timestamp == DateTime.MinValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MinValue"); throw new ArgumentException("Param cannot be DateTime.MinValue", nameof(timestamp)); } if (timestamp == DateTime.MaxValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MaxValue"); throw new ArgumentException("Param cannot be DateTime.MaxValue", nameof(timestamp)); } var notificationBuilder = new ReopenRequestedNotificationBuilder(_mapper, _uriHelper, _costStageRevisionService, _metadataProviderService, _appSettings, _efContext, _regionsService); return(await notificationBuilder.Build(cost, costUsers, requestedBy.FullName, costStageRevision, timestamp)); }
public async Task Create_Notification_For_Coupa_For_Non_NA_Non_Cyclone_Agency_When_Cost_Total_Amount_Decreased() { //Arrange decimal?previousPaymentAmount = 10.00M; decimal?latestPaymentAmount = 5.00M; //Decreased from 10 var timestamp = DateTime.UtcNow; var cost = new Cost(); var costOwner = new CostUser(); var latestRevision = new CostStageRevision(); var previousRevisionId = Guid.NewGuid(); var latestRevisionId = Guid.NewGuid(); SetupPurchaseOrderCost(cost, latestRevision, costOwner, previousRevisionId, latestRevisionId, PoNumber); var costUsers = new CostNotificationUsers { CostOwner = costOwner }; var previousPaymentResult = new PaymentAmountResult { TotalCostAmount = previousPaymentAmount }; var latestPaymentResult = new PaymentAmountResult { TotalCostAmount = latestPaymentAmount }; PgPaymentServiceMock.Setup(ppsm => ppsm.GetPaymentAmount(previousRevisionId, false)).Returns(Task.FromResult(previousPaymentResult)); PgPaymentServiceMock.Setup(ppsm => ppsm.GetPaymentAmount(latestRevisionId, false)).Returns(Task.FromResult(latestPaymentResult)); //Act IEnumerable <EmailNotificationMessage <CostNotificationObject> > result = await EmailNotificationBuilder.BuildPendingBrandApprovalNotification(costUsers, cost, latestRevision, timestamp); //Assert result.Should().NotBeNull(); var notifications = result.ToArray(); notifications.Should().HaveCount(1); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build( Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp, CostUser changeApprover, CostUser previousOwner) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); string actionType = core.Constants.EmailNotificationActionType.CostOwnerChanged; var costOwner = costUsers.CostOwner; //add recipients var recipients = new List <string> { costOwner.GdamUserId }; if (costUsers.Watchers != null) { recipients.AddRange(costUsers.Watchers); } if (costUsers.Approvers != null) { recipients.AddRange(costUsers.Approvers); } recipients.Add(previousOwner.GdamUserId); var costOwnerNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, recipients.Distinct()); AddSharedTo(costOwnerNotification); MapEmailNotificationObject(costOwnerNotification.Object, cost, costOwner); costOwnerNotification.Object.Cost.PreviousOwner = previousOwner.FullName; var approver = costOwnerNotification.Object.Approver; approver.Name = changeApprover.FullName; PopulateOtherFields(costOwnerNotification, core.Constants.EmailNotificationParents.CostOwner, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(costOwnerNotification.Object, cost.Id); notifications.Add(costOwnerNotification); return(notifications); }
protected async Task <EmailNotificationMessage <CostNotificationObject> > AddFinanceManagerNotification( string actionType, Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp, List <EmailNotificationMessage <CostNotificationObject> > notifications ) { //Only send to North American P&G Finance Users when Budget Region is North America and Cyclone costs if (costUsers.FinanceManagementUsers == null || !costUsers.FinanceManagementUsers.Any() || Constants.BudgetRegion.NorthAmerica != GetBudgetRegion(costStageRevision) || !costUsers.CostOwner.Agency.IsCyclone()) { return(null); } //Send to FinanceManagement as well var financeManagementNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, costUsers.FinanceManagementUsers); var notificationObject = new FinanceManagerCostNotificationObject(); financeManagementNotification.Object = notificationObject; var parent = core.Constants.EmailNotificationParents.FinanceManagement; AddSharedTo(financeManagementNotification); MapEmailNotificationObject(financeManagementNotification.Object, cost, costUsers); PopulateOtherFields(financeManagementNotification, parent, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(financeManagementNotification.Object, cost.Id); notifications.Add(financeManagementNotification); if (cost.Status == CostStageRevisionStatus.Approved && cost.LatestCostStageRevision.CostStage.Key == Models.Stage.CostStages.OriginalEstimate.ToString()) { notificationObject.CanAssignIONumber = true; } return(financeManagementNotification); }
private async Task BuildPendingBrandApprovalNotification(List <EmailNotificationMessage <CostNotificationObject> > notifications, List <Approval> approvals, Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var costOwner = costUsers.CostOwner; var agency = costOwner.Agency; var isCyclone = agency.IsCyclone(); var costStageRevisionId = costStageRevision.Id; var isNorthAmericanBudgetRegion = IsNorthAmericanBudgetRegion(costStageRevisionId); var brandApprovals = approvals.Where(a => a.Type == ApprovalType.Brand).ToArray(); if (isCyclone && isNorthAmericanBudgetRegion) { //Send notification to Brand Approver in the Platform for Cost in North American Budget Region and Cyclone agencies. const string actionType = core.Constants.EmailNotificationActionType.BrandApproverAssigned; var parent = core.Constants.EmailNotificationParents.BrandApprover; foreach (var brandApproval in brandApprovals) { foreach (var approvalMember in brandApproval.ApprovalMembers) { //Send notifications to actual Brand Approvers only if (approvalMember.IsSystemApprover()) { continue; } var approvalCostUser = approvalMember.CostUser; var brandApproverNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, approvalCostUser.GdamUserId); AddSharedTo(brandApproverNotification); MapEmailNotificationObject(brandApproverNotification.Object, cost, costOwner, approvalCostUser); PopulateOtherFields(brandApproverNotification, parent, timestamp, cost.Id, costStageRevisionId); await PopulateMetadata(brandApproverNotification.Object, cost.Id); notifications.Add(brandApproverNotification); if (ShouldNotifyInsuranceUsers(costUsers)) { var insuranceUserNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, costUsers.InsuranceUsers); AddSharedTo(insuranceUserNotification); MapEmailNotificationObject(insuranceUserNotification.Object, cost, costOwner, approvalCostUser); PopulateOtherFields(insuranceUserNotification, core.Constants.EmailNotificationParents.InsuranceUser, timestamp, cost.Id, costStageRevisionId); await PopulateMetadata(insuranceUserNotification.Object, cost.Id); notifications.Add(insuranceUserNotification); } } } if (brandApprovals.Any()) { await AddFinanceManagerNotification(actionType, cost, costUsers, costStageRevision, timestamp, notifications); } } else { AddCoupaApprovalEmail(notifications, cost, costOwner, costStageRevisionId, timestamp); } }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); //Build PendingBrandApproval notifications var approvals = _approvalService.GetApprovalsByCostStageRevisionId(costStageRevision.Id).Result; if (approvals != null) { await BuildPendingBrandApprovalNotification(notifications, approvals, cost, costUsers, costStageRevision, timestamp); } return(notifications); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); var approvals = _approvalService.GetApprovalsByCostStageRevisionId(costStageRevision.Id).Result; const string actionType = core.Constants.EmailNotificationActionType.TechnicalApproverAssigned; if (approvals == null) { //No approvals set return(notifications); } var costOwner = costUsers.CostOwner; var technicalApprovals = approvals.Where(a => a.Type == ApprovalType.IPM).ToArray(); foreach (var technicalApproval in technicalApprovals) { foreach (var approvalMember in technicalApproval.ApprovalMembers) { //Send notifications to Technical Approver var approvalCostUser = approvalMember.CostUser; var technicalApproverNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, approvalCostUser.GdamUserId); AddSharedTo(technicalApproverNotification); MapEmailNotificationObject(technicalApproverNotification.Object, cost, costOwner, approvalCostUser); PopulateOtherFields(technicalApproverNotification, core.Constants.EmailNotificationParents.TechnicalApprover, timestamp, cost.Id, costStageRevision.Id, approvalCostUser); await PopulateMetadata(technicalApproverNotification.Object, cost.Id); notifications.Add(technicalApproverNotification); //Insurance User if (ShouldNotifyInsuranceUsers(costUsers)) { var insuranceUserNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, costUsers.InsuranceUsers); AddSharedTo(insuranceUserNotification); MapEmailNotificationObject(insuranceUserNotification.Object, cost, costOwner, approvalCostUser); PopulateOtherFields(insuranceUserNotification, core.Constants.EmailNotificationParents.InsuranceUser, timestamp, cost.Id, costStageRevision.Id, approvalCostUser); await PopulateMetadata(insuranceUserNotification.Object, cost.Id); notifications.Add(insuranceUserNotification); } } } await AddFinanceManagerNotification(actionType, cost, costUsers, costStageRevision, timestamp, notifications); return(notifications); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(IEnumerable <ApprovalMember> removedApprovers, dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, CostStageRevision previousRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); foreach (var removedMember in removedApprovers) { if (removedMember.IsSystemApprover()) { continue; } var approvalCostUser = removedMember.CostUser; var costOwner = costUsers.CostOwner; string actionType = core.Constants.EmailNotificationActionType.ApproverUnassigned; string parent = core.Constants.EmailNotificationParents.Approver; var previousApproverNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, approvalCostUser.GdamUserId); AddSharedTo(previousApproverNotification); MapEmailNotificationObject(previousApproverNotification.Object, cost, costOwner, approvalCostUser); PopulateOtherFields(previousApproverNotification, parent, timestamp, cost.Id, previousRevision.Id); await PopulateMetadata(previousApproverNotification.Object, cost.Id); var replacement = GetReplacement(cost.LatestCostStageRevision, removedMember); var approver = previousApproverNotification.Object.Approver; approver.Type = GetApprovalType(removedMember.Approval); if (replacement != null) { approver.Name = replacement.CostUser.FullName; } notifications.Add(previousApproverNotification); } return(notifications); }
protected void MapEmailNotificationObject(CostNotificationObject obj, Cost cost, CostNotificationUsers users) { dataAccess.Entity.Project project = cost.Project; obj.Agency = Mapper.Map <core.Models.Notifications.Agency>(users.CostOwner.Agency); Mapper.Map(users.CostOwner.Agency.Country, obj.Agency); obj.Brand = Mapper.Map <core.Models.Notifications.Brand>(project.Brand); obj.Cost = Mapper.Map <core.Models.Notifications.Cost>(cost); Mapper.Map(cost.LatestCostStageRevision.CostStage, obj.Cost); Mapper.Map(users.CostOwner, obj.Cost); obj.Project = Mapper.Map <core.Models.Notifications.Project>(project); if (users.Approver != null) { obj.Approver = Mapper.Map <Approver>(users.Approver); } }
public async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > BuildCostApprovedNotification(CostNotificationUsers costUsers, Cost cost, CostStageRevision costStageRevision, string approverName, string approvalType, DateTime timestamp) { if (cost == null) { Logger.Error("Failed to create an email notification because cost is null."); throw new ArgumentNullException(nameof(cost)); } if (costStageRevision == null) { Logger.Error("Failed to create an email notification because costStageRevision is null."); throw new ArgumentNullException(nameof(costStageRevision)); } if (costUsers == null) { Logger.Error("Failed to create an email notification because costUsers is null."); throw new ArgumentNullException(nameof(costUsers)); } if (approverName == null) { Logger.Error("ENB001: Failed to create an email notification because approver is null. This could be because IoNumberOwner is empty from Coupa. The IoNumberOwner is the approver for Costs approved in Coupa."); throw new ArgumentNullException(nameof(approverName)); } if (timestamp == DateTime.MinValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MinValue"); throw new ArgumentException("Param cannot be DateTime.MinValue", nameof(timestamp)); } if (timestamp == DateTime.MaxValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MaxValue"); throw new ArgumentException("Param cannot be DateTime.MaxValue", nameof(timestamp)); } var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); var approvedNotificationBuilder = new ApprovedNotificationBuilder(_mapper, _uriHelper, _costStageRevisionService, _metadataProviderService, _appSettings, _efContext, _regionsService); notifications.AddRange(await approvedNotificationBuilder.Build(cost, costUsers, approverName, approvalType, costStageRevision, timestamp)); return(notifications); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > BuildAsync(Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); //Cost Owner var costOwner = costUsers.CostOwner; var actionType = Constants.EmailNotificationActionType.Recalled; var costOwnerNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, costOwner.GdamUserId); AddSharedTo(costOwnerNotification); MapEmailNotificationObject(costOwnerNotification.Object, cost, costOwner); await PopulateOtherFieldsForRecall(costOwnerNotification, Constants.EmailNotificationParents.CostOwner, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(costOwnerNotification.Object, cost.Id); notifications.Add(costOwnerNotification); var approvals = await _approvalService.GetApprovalsByCostStageRevisionId(costStageRevision.Id); if (approvals == null) { //No approvals set return(notifications); } var technicalApprovals = approvals.Where(a => a.Type == ApprovalType.IPM).ToArray(); foreach (var technicalApproval in technicalApprovals) { foreach (var approvalMember in technicalApproval.ApprovalMembers) { //Send notifications to Technical Approver await AddApproverNotification(notifications, cost, costOwner, costStageRevision, timestamp, actionType, approvalMember.CostUser); } } var brandApprovals = approvals.Where(a => a.Type == ApprovalType.Brand).ToArray(); foreach (var brandApproval in brandApprovals) { foreach (var approvalMember in brandApproval.ApprovalMembers) { //Send notifications to actual Brand Approvers only if (approvalMember.IsSystemApprover()) { continue; } await AddApproverNotification(notifications, cost, costOwner, costStageRevision, timestamp, actionType, approvalMember.CostUser); } if (brandApproval.Requisitioners == null) { continue; } foreach (var requisitioner in brandApproval.Requisitioners) { await AddApproverNotification(notifications, cost, costOwner, costStageRevision, timestamp, actionType, requisitioner.CostUser); } } await AddFinanceManagerNotification(actionType, cost, costUsers, costStageRevision, timestamp, notifications); return(notifications); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(Cost cost, CostNotificationUsers costUsers, string approverName, string approvalType, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); //Cost Owner string actionType; var parent = core.Constants.EmailNotificationParents.CostOwner; if (approvalType == core.Constants.EmailApprovalType.Brand) { actionType = core.Constants.EmailNotificationActionType.BrandApprovalApproved; approvalType = await GetBrandManagerRoleLabel(); if (cost.IsExternalPurchases) { parent = core.Constants.EmailNotificationParents.MyPurchases; } } else { actionType = core.Constants.EmailNotificationActionType.TechnicalApprovalApproved; } var costOwner = costUsers.CostOwner; var recipients = new List <string> { costOwner.GdamUserId }; if (costUsers.Watchers != null) { recipients.AddRange(costUsers.Watchers); } var costOwnerNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, recipients); AddSharedTo(costOwnerNotification); MapEmailNotificationObject(costOwnerNotification.Object, cost, costOwner); PopulateOtherFields(costOwnerNotification, parent, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(costOwnerNotification.Object, cost.Id); var approver = costOwnerNotification.Object.Approver; approver.Name = approverName; approver.Type = approvalType; notifications.Add(costOwnerNotification); if (cost.Status == CostStageRevisionStatus.Approved) { if (ShouldNotifyInsuranceUsers(costUsers)) { //Send to all InsuranceUsers as well var insuranceUsers = costUsers.InsuranceUsers; var insuranceUserNotification = new EmailNotificationMessage <CostNotificationObject>(core.Constants.EmailNotificationActionType.AllApprovalsApproved, insuranceUsers); parent = core.Constants.EmailNotificationParents.InsuranceUser; AddSharedTo(insuranceUserNotification); MapEmailNotificationObject(insuranceUserNotification.Object, cost, costUsers); PopulateOtherFields(insuranceUserNotification, parent, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(insuranceUserNotification.Object, cost.Id); approver = insuranceUserNotification.Object.Approver; approver.Name = approverName; approver.Type = approvalType; notifications.Add(insuranceUserNotification); } var financeManagementNotification = await AddFinanceManagerNotification(core.Constants.EmailNotificationActionType.AllApprovalsApproved, cost, costUsers, costStageRevision, timestamp, notifications); if (financeManagementNotification != null) { approver = financeManagementNotification.Object.Approver; approver.Name = approverName; approver.Type = approvalType; } } return(notifications); }
public async Task <bool> CostHasBeenApproved(Guid costId, Guid approverUserId, string approvalType) { if (costId == Guid.Empty) { return(false); } if (approverUserId == Guid.Empty) { return(false); } if (string.IsNullOrWhiteSpace(approvalType)) { return(false); } if (!IsValidApprovalType(approvalType)) { return(false); } var cost = await _efContext.Cost .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .Include(c => c.Project) .ThenInclude(p => p.Brand) .IncludeCostOwner() .FirstOrDefaultAsync(c => c.Id == costId); var costStageRevision = cost.LatestCostStageRevision; var approver = await _costUserService.GetApprover(costId, approverUserId, approvalType); var costOwner = cost.Owner; var financeManagementUsers = await _costUserService.GetFinanceManagementUsers(cost.UserGroups, Constants.BudgetRegion.NorthAmerica); var insuranceUsers = await _costUserService.GetInsuranceUsers(costOwner.Agency); var costUsers = new CostNotificationUsers { CostOwner = costOwner, FinanceManagementUsers = financeManagementUsers, InsuranceUsers = insuranceUsers, Watchers = await GetWatchers(costId) }; var notificationMessages = await _emailNotificationBuilder.BuildCostApprovedNotification(costUsers, cost, costStageRevision, approver, approvalType, DateTime.UtcNow); var notifications = notificationMessages.ToList(); if (approvalType != core.Constants.EmailApprovalType.Brand) { //Technical Approval sent so now send Brand Approval email notifications.AddRange(await _emailNotificationBuilder.BuildPendingBrandApprovalNotification(costUsers, cost, costStageRevision, DateTime.UtcNow)); //For Technical Approval, cancel the reminder, if any await _reminderService.CancelReminder(cost.Id); //Enqueue reminder for the brand approvers. await _reminderService.CreateNew(cost.Id, DateTime.UtcNow.AddDays(1)); } if (approvalType == core.Constants.EmailApprovalType.Brand) { //For Brand Approval, cancel the reminder, if any await _reminderService.CancelReminder(cost.Id); } bool sent = false; foreach (var message in notifications) { sent = await _paperPusherClient.SendMessage(message); } return(sent); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); //Cost Owner var costOwner = costUsers.CostOwner; var costOwnerNotification = new EmailNotificationMessage <CostNotificationObject>( core.Constants.EmailNotificationActionType.Submitted, costOwner.GdamUserId); AddSharedTo(costOwnerNotification); MapEmailNotificationObject(costOwnerNotification.Object, cost, costOwner); PopulateOtherFields(costOwnerNotification, core.Constants.EmailNotificationParents.CostOwner, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(costOwnerNotification.Object, cost.Id); notifications.Add(costOwnerNotification); return(notifications); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); var approvals = await _approvalService.GetApprovalsByCostStageRevisionId(costStageRevision.Id); if (approvals == null) { //No approvals set return(notifications); } await BuildPendingTechnicalApprovalNotification(notifications, approvals, cost, costUsers, costUsers.CostOwner, costStageRevision, timestamp); return(notifications); }
private async Task BuildPendingTechnicalApprovalNotification(List <EmailNotificationMessage <CostNotificationObject> > notifications, List <Approval> approvals, dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, CostUser costOwner, CostStageRevision costStageRevision, DateTime timestamp) { const string actionType = core.Constants.EmailNotificationActionType.TechnicalApproverSendReminder; var technicalApprovals = approvals.Where(a => a.Type == ApprovalType.IPM).ToArray(); foreach (var technicalApproval in technicalApprovals) { foreach (var approvalMember in technicalApproval.ApprovalMembers) { //Send notifications to Technical Approver var approvalCostUser = approvalMember.CostUser; var technicalApproverNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, approvalCostUser.GdamUserId); AddSharedTo(technicalApproverNotification); MapEmailNotificationObject(technicalApproverNotification.Object, cost, costOwner, approvalCostUser); PopulateOtherFields(technicalApproverNotification, core.Constants.EmailNotificationParents.TechnicalApprover, timestamp, cost.Id, costStageRevision.Id, approvalCostUser); await PopulateMetadata(technicalApproverNotification.Object, cost.Id); notifications.Add(technicalApproverNotification); } } }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, string approverName, string approvalType, string comments, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); const string actionType = core.Constants.EmailNotificationActionType.Rejected; //Cost Owner var costOwner = costUsers.CostOwner; var recipients = new List <string> { costOwner.GdamUserId }; recipients.AddRange(costUsers.Watchers); var costOwnerNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, recipients); AddSharedTo(costOwnerNotification); MapEmailNotificationObject(costOwnerNotification.Object, cost, costOwner); PopulateOtherFields(costOwnerNotification, core.Constants.EmailNotificationParents.CostOwner, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(costOwnerNotification.Object, cost.Id); var obj = costOwnerNotification.Object; var approver = obj.Approver; approver.Name = approverName; approver.Type = approvalType; obj.Comments = comments; notifications.Add(costOwnerNotification); if (ShouldNotifyInsuranceUsers(costUsers)) { var insuranceUserNotification = new EmailNotificationMessage <CostNotificationObject>(actionType, costUsers.InsuranceUsers); AddSharedTo(insuranceUserNotification); MapEmailNotificationObject(insuranceUserNotification.Object, cost, costOwner); PopulateOtherFields(insuranceUserNotification, core.Constants.EmailNotificationParents.InsuranceUser, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(insuranceUserNotification.Object, cost.Id); obj = insuranceUserNotification.Object; approver = obj.Approver; approver.Name = approverName; approver.Type = approvalType; obj.Comments = comments; notifications.Add(insuranceUserNotification); } await AddFinanceManagerNotification(actionType, cost, costUsers, costStageRevision, timestamp, notifications); return(notifications); }
internal async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > Build(dataAccess.Entity.Cost cost, CostNotificationUsers costUsers, string requestedByName, CostStageRevision costStageRevision, DateTime timestamp) { var notifications = new List <EmailNotificationMessage <CostNotificationObject> >(); //Admin Notification - one notification object for all admins var adminIds = costUsers.ClientAdmins.Select(x => x.GdamUserId).ToList(); var adminNotification = new EmailNotificationMessage <CostNotificationObject>(core.Constants.EmailNotificationActionType.ReopenRequested, adminIds); AddSharedTo(adminNotification); MapEmailNotificationObject(adminNotification.Object, cost, costUsers.CostOwner); PopulateOtherFields(adminNotification, string.Empty, timestamp, cost.Id, costStageRevision.Id); await PopulateMetadata(adminNotification.Object, cost.Id); adminNotification.Object.Approver.Name = requestedByName; notifications.Add(adminNotification); await AddFinanceManagerNotification(core.Constants.EmailNotificationActionType.CostStatus, cost, costUsers, costStageRevision, timestamp, notifications); return(notifications); }
public async Task <bool> CostHasBeenSubmitted(Guid costId, Guid userId) { if (costId == Guid.Empty) { return(false); } if (userId == Guid.Empty) { return(false); } var cost = await _efContext.Cost .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .ThenInclude(cs => cs.CostStageRevisions) .Include(c => c.LatestCostStageRevision) .Include(c => c.CostStages) .ThenInclude(cs => cs.CostStageRevisions) .ThenInclude(csr => csr.Approvals) .ThenInclude(a => a.ApprovalMembers) .ThenInclude(am => am.CostUser) .Include(c => c.Project) .ThenInclude(p => p.Brand) .IncludeCostOwner() .FirstOrDefaultAsync(c => c.Id == costId); var latestRevision = cost.LatestCostStageRevision; var costOwner = cost.Owner; var insuranceUsers = await _costUserService.GetInsuranceUsers(costOwner.Agency); var financeManagementUsers = await _costUserService.GetFinanceManagementUsers(cost.UserGroups, Constants.BudgetRegion.NorthAmerica); var costUsers = new CostNotificationUsers { CostOwner = cost.Owner, InsuranceUsers = insuranceUsers, FinanceManagementUsers = financeManagementUsers }; var notificationMessages = await _emailNotificationBuilder.BuildCostSubmittedNotification(costUsers, cost, latestRevision, DateTime.UtcNow); var notifications = notificationMessages.ToList(); //Upon Submit the next stage might be PendingTechnicalApproval or PendingBrandApproval or Approved for FA. var nextStatus = cost.Status; switch (nextStatus) { case CostStageRevisionStatus.Approved: // The Cost is auto approved when the budget does not change between cost stages. await BuildAutoApprovedNotification(costUsers, cost, latestRevision, notifications); break; case CostStageRevisionStatus.PendingBrandApproval: var pendingBrandNotifications = await _emailNotificationBuilder.BuildPendingBrandApprovalNotification(costUsers, cost, latestRevision, DateTime.UtcNow); notifications.AddRange(pendingBrandNotifications); //Enqueue reminder for the brand approvers. await _reminderService.CreateNew(cost.Id, DateTime.UtcNow.AddDays(1)); break; case CostStageRevisionStatus.PendingTechnicalApproval: var pendingTechnicalNotifications = await _emailNotificationBuilder.BuildPendingTechnicalApprovalNotification(costUsers, cost, latestRevision, DateTime.UtcNow); notifications.AddRange(pendingTechnicalNotifications); break; //ADC-2698 comment this line of code to take off the feature from release 1.9.4 // //Enqueue reminder for the technical approvers. // await _reminderService.CreateNew(cost.Id, DateTime.UtcNow.AddDays(2)); // break; } //Notify previous approvers if they've been removed if (cost.HasPreviousRevision()) { var previousRevision = cost.GetPreviousRevision(); var previousRevisionId = previousRevision.Id; //Get the approvers for the previous revision previousRevision.Approvals = await _approvalService.GetApprovalsByCostStageRevisionId(previousRevisionId); var csrAnalyser = new CostStageRevisionAnalyser(); IEnumerable <ApprovalMember> removedApprovers = csrAnalyser.GetRemovedApprovers(previousRevision, latestRevision); var removedApproverNotifications = await _emailNotificationBuilder.BuildPreviousApproverNotification(costUsers, removedApprovers, cost, previousRevision, DateTime.UtcNow); notifications.AddRange(removedApproverNotifications); } bool sent = false; foreach (var message in notifications) { sent = await _paperPusherClient.SendMessage(message); } return(sent); }
public async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > BuildCostReminderNotification(CostNotificationUsers costUsers, Cost cost, CostStageRevision costStageRevision, DateTime timestamp) { if (cost == null) { Logger.Error("Failed to create an email notification because cost is null."); throw new ArgumentNullException(nameof(cost)); } if (costStageRevision == null) { Logger.Error("Failed to create an email notification because costStageRevision is null."); throw new ArgumentNullException(nameof(costStageRevision)); } if (costUsers == null) { Logger.Error("Failed to create an email notification because costUsers is null."); throw new ArgumentNullException(nameof(costUsers)); } if (timestamp == DateTime.MinValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MinValue"); throw new ArgumentException("Param cannot be DateTime.MinValue", nameof(timestamp)); } if (timestamp == DateTime.MaxValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MaxValue"); throw new ArgumentException("Param cannot be DateTime.MaxValue", nameof(timestamp)); } //ADC-2698 send notification to technical approver var notificationMessages = new List <EmailNotificationMessage <CostNotificationObject> >(); if (costStageRevision.Status == CostStageRevisionStatus.PendingTechnicalApproval) { var pendingTechnicalNotificationBuilder = new ReminderPendingTechnicalNotificationBuilder(_mapper, _uriHelper, _costStageRevisionService, _metadataProviderService, _approvalService, _appSettings, _efContext, _regionsService); notificationMessages.AddRange(await pendingTechnicalNotificationBuilder.Build(cost, costUsers, costStageRevision, timestamp)); } else if (costStageRevision.Status == CostStageRevisionStatus.PendingBrandApproval) { var pendingBrandNotificationBuilder = new ReminderPendingBrandNotificationBuilder(_mapper, _uriHelper, _costStageRevisionService, _approvalService, _metadataProviderService, _regionsService, _appSettings, _efContext); notificationMessages.AddRange(await pendingBrandNotificationBuilder.Build(cost, costUsers, costStageRevision, timestamp)); } return(notificationMessages); }
public async Task <bool> CostOwnerHasChanged(Guid costId, Guid userId, Guid previousOwnerId) { if (costId == Guid.Empty) { return(false); } if (userId == Guid.Empty) { return(false); } if (previousOwnerId == Guid.Empty) { return(false); } var cost = await _efContext.Cost .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .ThenInclude(cs => cs.CostStageRevisions) .Include(c => c.Project) .ThenInclude(p => p.Brand) .IncludeCostOwner() .FirstOrDefaultAsync(c => c.Id == costId); var latestRevision = cost.LatestCostStageRevision; var costOwner = cost.Owner; var previousOwner = await _efContext.CostUser.FirstOrDefaultAsync(x => x.Id == previousOwnerId); var changeApprover = await _efContext.CostUser.FirstOrDefaultAsync(x => x.Id == userId); var insuranceUsers = await _costUserService.GetInsuranceUsers(costOwner.Agency); var watchers = await GetWatchers(costId); var approvals = _approvalService.GetApprovalsByCostStageRevisionId(latestRevision.Id).Result; var approvers = approvals?.SelectMany(a => a.ApprovalMembers .Where(m => m.CostUser.Email != core.Builders.Response.ApprovalMemberModel.BrandApprovalUserEmail) .Select(m => m.CostUser.GdamUserId)) ?? new List <string>(); var costUsers = new CostNotificationUsers { CostOwner = cost.Owner, InsuranceUsers = insuranceUsers, Watchers = watchers, Approvers = approvers, }; var notificationMessages = await _emailNotificationBuilder.BuildCostOwnerChangedNotification(costUsers, cost, latestRevision, DateTime.UtcNow, changeApprover, previousOwner); var notifications = notificationMessages.ToList(); bool sent = false; foreach (var message in notifications) { sent = await _paperPusherClient.SendMessage(message); } return(sent); }
public async Task <IEnumerable <EmailNotificationMessage <CostNotificationObject> > > BuildCostSubmittedNotification(CostNotificationUsers costUsers, Cost cost, CostStageRevision costStageRevision, DateTime timestamp) { if (cost == null) { Logger.Error("Failed to create an email notification because cost is null."); throw new ArgumentNullException(nameof(cost)); } if (costStageRevision == null) { Logger.Error("Failed to create an email notification because costStageRevision is null."); throw new ArgumentNullException(nameof(costStageRevision)); } if (costUsers == null) { Logger.Error("Failed to create an email notification because costUsers is null."); throw new ArgumentNullException(nameof(costUsers)); } if (timestamp == DateTime.MinValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MinValue"); throw new ArgumentException("Param cannot be DateTime.MinValue", nameof(timestamp)); } if (timestamp == DateTime.MaxValue) { Logger.Error("Failed to create an email notification because system timestamp provided was DateTime.MaxValue"); throw new ArgumentException("Param cannot be DateTime.MaxValue", nameof(timestamp)); } var submittedNotificationBuilder = new SubmittedNotificationBuilder(_mapper, _uriHelper, _costStageRevisionService, _metadataProviderService, _appSettings, _efContext, _regionsService); return(await submittedNotificationBuilder.Build(cost, costUsers, costStageRevision, timestamp)); }
private async Task ProcessReminders(StringBuilder logMessages) { try { _emailNotificationReminderService.ReminderUpdateToSending(); List <EmailNotificationReminder> sentReminders = new List <EmailNotificationReminder>(); Dictionary <EmailNotificationReminder, EmailReminderStatus> updateReminders = new Dictionary <EmailNotificationReminder, EmailReminderStatus>(); var remindingEmails = await _emailNotificationReminderService.GetEmailNotificationReminderByStatus(EmailReminderStatus.Reminding, 10); List <CostStageRevisionStatus> invalidStatuses = new List <CostStageRevisionStatus>(); invalidStatuses.Add(CostStageRevisionStatus.PendingBrandApproval); invalidStatuses.Add(CostStageRevisionStatus.PendingTechnicalApproval); List <CostStageRevisionStatus> approvedStatuses = new List <CostStageRevisionStatus>(); approvedStatuses.Add(CostStageRevisionStatus.Approved); foreach (var reminder in remindingEmails) { logMessages.AppendLine($"START: sending reminder for cost: {reminder.CostId}"); //Get the cost var cost = await _efContext.Cost .AsNoTracking() .Include(c => c.LatestCostStageRevision) .ThenInclude(csr => csr.CostStage) .Include(c => c.Project) .ThenInclude(p => p.Brand) .Include(c => c.Owner) .ThenInclude(o => o.Agency) .ThenInclude(a => a.Country) .FirstAsync(c => c.Id == reminder.CostId); var users = new CostNotificationUsers { CostOwner = cost.Owner }; if (approvedStatuses.Contains(cost.LatestCostStageRevision.Status)) { updateReminders.Add(reminder, EmailReminderStatus.Reminded); } else if (invalidStatuses.Contains(cost.LatestCostStageRevision.Status)) { //Build var notificationMessages = await _emailNotificationBuilder.BuildCostReminderNotification(users, cost, cost.LatestCostStageRevision, DateTime.UtcNow); //Send bool sent = false; foreach (var notification in notificationMessages) { sent = await _paperpusherClient.SendMessage(notification); if (!sent) { logMessages.AppendLine($"[Error] Failed to send notification for cost: {reminder.CostId}"); } } //Update if (sent) { sentReminders.Add(reminder); logMessages.AppendLine($"FINISHED: Sent reminder for cost: {reminder.CostId}"); } } else { updateReminders.Add(reminder, EmailReminderStatus.Cancelled); } } _emailNotificationReminderService.ReminderUpdateToSent(sentReminders); _emailNotificationReminderService.ReminderUpdateToSent(updateReminders); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }