public static void SendApprovalRequestEmail( [ActivityTrigger] ApprovalInfo approvalInfo, [SendGrid(ApiKey = "SendGridKey")] out SendGridMessage message, [Table("Approvals", "AzureWebJobsStorage")] out Approval approval, ILogger log) { var approvalCode = Guid.NewGuid().ToString("N"); approval = new Approval { PartitionKey = "Approval", RowKey = approvalCode, OrchestrationId = approvalInfo.OrchestrationId }; var subject = "An activity is awaiting approval"; var host = Environment.GetEnvironmentVariable("Host"); var functionAddress = $"{host}/api/SubmitApproval/{approvalCode}"; var approvedLink = functionAddress + "?result=Approved"; var rejectedLink = functionAddress + "?result=Rejected"; var body = $"Please {approvalInfo.Message}<br>" + $"<a href=\"{approvedLink}\">Approve</a><br>" + $"<a href=\"{rejectedLink}\">Reject</a>"; message = new SendGridMessage(); message.AddTo(Environment.GetEnvironmentVariable("ApproverEmail")); message.AddContent("text/html", body); message.SetFrom(new EmailAddress(Environment.GetEnvironmentVariable("SenderEmail"))); message.SetSubject(subject); }
public async Task <JsonResult> Approval(int?id, bool status, string comment) { if (id == null) { return(Json(new { message = $"Reciept not found" })); } var travelInfo = await _travelService .FindByIdAsync(m => m.ID == id); if (travelInfo == null) { return(Json(new { message = $"Reciept not found" })); } travelInfo.IsApproved = status; await Task.Run(async() => { var approvalInfo = await _approvalInfoService.FindByIdAsync(m => m.TravelID == id); if (approvalInfo != null) { approvalInfo.IsApproved = status; approvalInfo.ApprovedDate = DateTime.Now; approvalInfo.Comment = comment; approvalInfo.ApprovedBy = User.Identity.Name; await _approvalInfoService.UpdateAsync(approvalInfo); } else { var approveReciept = new ApprovalInfo { IsApproved = status, ApprovedBy = User.Identity.Name, TravelID = id ?? default(int), Comment = comment, ApprovedDate = DateTime.Now }; await _approvalInfoService.AddAsync(approveReciept); } if (status) { await SendMailToFinanceAsync(travelInfo.RecieptDoc); } }); return(Json(new { message = $"The travel expenses with purpose {travelInfo.Purpose}'s status has Updated" })); }
// STEP 5: Handle callback from notification subscriber void OnIncreaseResponse(ApprovalInfo approve) { // Set message text string resultText = approve.Result ? "approved" : "rejected"; MessageText = $"Order quantity of {approve.Amount} {resultText} for {approve.CustomerName}"; MessageVisibility = Visibility.Visible; // Reverse increase if rejected if (!approve.Result) { SelectedCustomer.Orders -= 1000; } }
private void GetApproval(NotificationEventArgs <IncreaseInfo, ApprovalInfo> e) { // Prompt user for approval ApproveIncreaseView appoveView = new ApproveIncreaseView(e.Data); appoveView.Closed += (s, ea) => { // Callback notifier with result ApprovalInfo approveInfo = new ApprovalInfo (Customer.CustomerName, e.Data.Amount, appoveView.DialogResult != null && (bool)appoveView.DialogResult); e.Completed(approveInfo); }; appoveView.ShowDialog(); }
public static ApprovalInfoDTO ToDTO(ApprovalInfo approvalInfo) { if (approvalInfo == null) { return(null); } var dto = new ApprovalInfoDTO() { ApprovalInfoId = approvalInfo.ApprovalInfoId, Msg = approvalInfo.Msg, Time = approvalInfo.Time }; return(dto); }
private ApprovalInfoPO ApprovalInfoPOFromDO(ApprovalInfo approvalInfo, string aplicantId = null, string leaveID = null) { var approvalInfoPO = new ApprovalInfoPO() { ApplicantId = aplicantId, LeaveId = leaveID, ApprovalType = approvalInfo.ApprovalType, ApproverId = approvalInfo.Approver.PersonId, ApproverLevel = approvalInfo.ApproverLevel, ApproverName = approvalInfo.Approver.PersonName, ApprovalInfoId = string.IsNullOrEmpty(approvalInfo.ApprovalInfoId) ? Guid.NewGuid().ToString() : approvalInfo.ApprovalInfoId, Msg = approvalInfo.Msg, Time = approvalInfo.Time }; return(approvalInfoPO); }
private ApprovalInfo ApprovalInfoFromPO(ApprovalInfoPO approvalInfoPO) { var approvalInfo = new ApprovalInfo(); approvalInfo.ApprovalInfoId = approvalInfoPO.ApprovalInfoId; var approver = new Approver() { PersonId = approvalInfoPO.ApproverId, PersonName = approvalInfoPO.ApproverName, Level = approvalInfoPO.ApproverLevel }; approvalInfo.Approver = approver; approvalInfo.Msg = approvalInfoPO.Msg; approvalInfo.Time = approvalInfoPO.Time; return(approvalInfo); }
public static ApprovalInfo ToDO(ApprovalInfoDTO dto) { if (dto == null) { return(null); } var approvalInfo = new ApprovalInfo() { ApprovalType = dto.ApprovalType, Time = dto.Time, ApprovalInfoId = dto.ApprovalInfoId, Msg = dto.Msg, Approver = ApproverAssembler.ToDO(dto.ApproverDTO) }; return(approvalInfo); }
/// <summary> /// Add in approval steps to either the order or split, depending on what is provided /// </summary> /// <param name="order">The order</param> /// <param name="approvalInfo">list of approval people (or null) to route to</param> /// <param name="split">optional split to approve against instead of the order</param> /// <param name="minLevel">Min level only adds approvals at or above the provided level</param> private void AddApprovalSteps(Order order, ApprovalInfo approvalInfo, Split split, int minLevel = 0) { var approvals = new List<Approval> { new Approval { Completed = AutoApprovable(order, split, approvalInfo.Approver), //If this is auto approvable just include it but mark it as approval already User = approvalInfo.Approver, StatusCode = _repositoryFactory.OrderStatusCodeRepository.GetById(OrderStatusCode.Codes.Approver) }, new Approval { Completed = false, User = approvalInfo.AcctManager, StatusCode = _repositoryFactory.OrderStatusCodeRepository.GetById(OrderStatusCode.Codes.AccountManager), IsExternal = approvalInfo.IsExternal }, new Approval { Completed = false, User = approvalInfo.Purchaser, StatusCode = _repositoryFactory.OrderStatusCodeRepository.GetById(OrderStatusCode.Codes.Purchaser) } }; if (minLevel > 0) { approvals = approvals.Where(x => x.StatusCode.Level >= minLevel).ToList(); } foreach (var approval in approvals) { if (approval.StatusCode.Id == OrderStatusCode.Codes.Purchaser) { //Make sure to only add one purchaser approval if (order.Approvals.Any(x => x.StatusCode.Id == OrderStatusCode.Codes.Purchaser)) continue; } if (approval.StatusCode.Id == OrderStatusCode.Codes.Approver && approvalInfo.IsExternal) { continue; //Do not add approvals at the AP level for external accounts } split.AssociateApproval(approval); if (approval.Completed) { //already approved means auto approval, so send that specific event _eventService.OrderAutoApprovalAdded(order, approval); } else { _eventService.OrderApprovalAdded(order, approval); } } }
/// <summary> /// Recreates approvals for the given order, removing all approvals at or above the current order level /// Should not affect conditional approvals? /// </summary> public void ReRouteApprovalsForExistingOrder(Order order, string approverId = null, string accountManagerId = null) { var currentLevel = order.StatusCode.Level; //Remove all approvals at the current level or above var approvalsToRemove = order.Approvals.Where(x => x.StatusCode.Level >= currentLevel && x.StatusCode.Id != OrderStatusCode.Codes.ConditionalApprover).ToList(); foreach (var approval in approvalsToRemove) { order.Approvals.Remove(approval); } //recreate approvals if (!string.IsNullOrWhiteSpace(accountManagerId) && order.Splits.Count == 1) { //If we have an account manager assigned directly and only one split, use direct assigning for creating approvals var approvalInfo = new ApprovalInfo(); var split = order.Splits.Single(); approvalInfo.Approver = string.IsNullOrWhiteSpace(approverId) ? null : _repositoryFactory.UserRepository.GetById(approverId); approvalInfo.AcctManager = GetManager(accountManagerId); AddApprovalSteps(order, approvalInfo, split, currentLevel); } else { foreach (var split in order.Splits) { var approvalInfo = new ApprovalInfo(); //Try to find the account in the workgroup so we can route it by users var workgroupAccount = _repositoryFactory.WorkgroupAccountRepository.Queryable.FirstOrDefault(x => x.Account.Id == split.Account && x.Workgroup.Id == order.Workgroup.Id); approvalInfo.AccountId = split.Account; approvalInfo.IsExternal = (workgroupAccount == null); //if we can't find the account in the workgroup it is external if (workgroupAccount != null) //route to the people contained in the workgroup account info { approvalInfo.Approver = workgroupAccount.Approver; approvalInfo.AcctManager = workgroupAccount.AccountManager; approvalInfo.Purchaser = workgroupAccount.Purchaser; } else { //account is not in the workgroup var externalAccount = _repositoryFactory.AccountRepository.GetNullableById(split.Account); approvalInfo.Approver = null; approvalInfo.AcctManager = externalAccount != null ? _securityService.GetUser(externalAccount.AccountManagerId) : null; approvalInfo.Purchaser = null; } AddApprovalSteps(order, approvalInfo, split, currentLevel); } } order.StatusCode = GetCurrentOrderStatus(order); _eventService.OrderReRouted(order); }
/// <summary> /// Will add the proper approval levels to an order. If a workgroup account or approver/acctManager is passed in, a split is not possible /// </summary> /// <param name="order">The order. If it does not contain splits, you must pass along either workgroupAccount or acctManager</param> /// <param name="conditionalApprovalIds">The Ids of required conditional approvals for this order (the ones answered "yes")</param> /// <param name="accountId">Optional id of an account to use for routing</param> /// <param name="approverId">Optional approver userID</param> /// <param name="accountManagerId">AccountManager userID, required if account is not supplied</param> public void CreateApprovalsForNewOrder(Order order, int[] conditionalApprovalIds = null, string accountId = null, string approverId = null, string accountManagerId = null) { var approvalInfo = new ApprovalInfo(); if (order.Splits.Count() == 1) //Order has one split and can thus optionally not have accounts assigned { var split = order.Splits.Single(); Check.Require(!string.IsNullOrWhiteSpace(accountId) || !string.IsNullOrWhiteSpace(accountManagerId), "You must either supply the ID of a valid account or provide the userId for an account manager"); if (!string.IsNullOrWhiteSpace(accountId)) //if we route by account, use that for info { //TODO: move this code to a private methods as very similar code is used elsewhere here. var workgroupAccount = _repositoryFactory.WorkgroupAccountRepository.Queryable.FirstOrDefault(x => x.Account.Id == accountId && x.Workgroup.Id == order.Workgroup.Id); approvalInfo.AccountId = accountId; approvalInfo.IsExternal = (workgroupAccount == null); //if we can't find the account in the workgroup it is external if (workgroupAccount != null) //route to the people contained in the workgroup account info { approvalInfo.Approver = workgroupAccount.Approver; approvalInfo.AcctManager = workgroupAccount.AccountManager; approvalInfo.Purchaser = workgroupAccount.Purchaser; } else //account is not in the workgroup, even if we don't find the account, we will still use it { var externalAccount = _repositoryFactory.AccountRepository.GetNullableById(accountId); approvalInfo.Approver = null; approvalInfo.AcctManager = externalAccount != null ? _securityService.GetUser(externalAccount.AccountManagerId) : null; approvalInfo.Purchaser = null; } split.Account = accountId; //Assign the account to the split } else //else stick with user provided values { approvalInfo.Approver = string.IsNullOrWhiteSpace(approverId) ? null : _repositoryFactory.UserRepository.GetById(approverId); approvalInfo.AcctManager = GetManager(accountManagerId); } AddApprovalSteps(order, approvalInfo, split); } else //else order has multiple splits and each one needs an account { foreach (var split in order.Splits) { //Try to find the account in the workgroup so we can route it by users var workgroupAccount = _repositoryFactory.WorkgroupAccountRepository.Queryable.FirstOrDefault(x => x.Account.Id == split.Account && x.Workgroup.Id == order.Workgroup.Id); approvalInfo.AccountId = split.Account; approvalInfo.IsExternal = workgroupAccount == null; //if we can't find the account in the workgroup it is external if (workgroupAccount != null) //route to the people contained in the workgroup account info { approvalInfo.Approver = workgroupAccount.Approver; approvalInfo.AcctManager = workgroupAccount.AccountManager; approvalInfo.Purchaser = workgroupAccount.Purchaser; } else { //account is not in the workgroup var externalAccount = _repositoryFactory.AccountRepository.GetNullableById(split.Account); approvalInfo.Approver = null; approvalInfo.AcctManager = externalAccount != null ? _securityService.GetUser(externalAccount.AccountManagerId) : null; approvalInfo.Purchaser = null; } AddApprovalSteps(order, approvalInfo, split); } } //If we were passed conditional approval info, go ahead and add them if (conditionalApprovalIds != null && conditionalApprovalIds.Any()) { foreach (var conditionalApprovalId in conditionalApprovalIds) { var id = conditionalApprovalId; var approverIds = _repositoryFactory.ConditionalApprovalRepository.Queryable.Where(x => x.Id == id) .Select(x => new { primaryApproverId = x.PrimaryApprover.Id, secondaryApproverId = x.SecondaryApprover != null ? x.SecondaryApprover.Id : null } ).Single(); var newApproval = new Approval //Add a new 'approver' level approval { Completed = false, User = _repositoryFactory.UserRepository.GetById(approverIds.primaryApproverId), SecondaryUser = approverIds.secondaryApproverId == null ? null : _repositoryFactory.UserRepository.GetById(approverIds.secondaryApproverId), StatusCode = _repositoryFactory.OrderStatusCodeRepository.Queryable.Single(x => x.Id == OrderStatusCode.Codes.ConditionalApprover) }; order.AddApproval(newApproval);//Add directly to the order since conditional approvals never go against splits } } if (order.Workgroup.RequireApproval && !order.Approvals.Any(a => a.StatusCode.Id == OrderStatusCode.Codes.Approver)) { // Ok, we don't have any approvals (because an external account was used), so we want to add one. var missingApproval = new Approval { Completed = false, User = null, SecondaryUser = null, StatusCode = _repositoryFactory.OrderStatusCodeRepository.Queryable.Single( x => x.Id == OrderStatusCode.Codes.Approver) }; order.AddApproval(missingApproval); } order.StatusCode = GetCurrentOrderStatus(order); _eventService.OrderCreated(order); //Creating approvals means the order is being created }