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"
            }));
        }
Exemple #3
0
        // 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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #9
0
        /// <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);
                }
            }
        }
Exemple #10
0
        /// <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);
        }
Exemple #11
0
        /// <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
        }