Ejemplo n.º 1
0
        private async Task SaveResponse(PgPurchaseOrderResponse payload, Cost cost, SystemAdminUserIdentity adminUser)
        {
            var purchaseOrderData = await _customDataService
                                    .GetCustomData <PgPurchaseOrderResponse>(cost.LatestCostStageRevisionId.Value, CustomObjectDataKeys.PgPurchaseOrderResponse)
                                    ?? new PgPurchaseOrderResponse();

            _mapper.Map(payload, purchaseOrderData);
            if (string.Compare(payload.ApprovalStatus, ApprovalStatuses.Rejected, StringComparison.OrdinalIgnoreCase) == 0)
            {
                //null requisition ID should be allowed here
                purchaseOrderData.Requisition    = payload.Requisition;
                purchaseOrderData.ApprovalStatus = payload.ApprovalStatus;
            }

            await _customDataService.Save(cost.LatestCostStageRevisionId.Value, CustomObjectDataKeys.PgPurchaseOrderResponse, purchaseOrderData, adminUser);

            await UpdatePaymentDetails(cost.LatestCostStageRevisionId.Value, purchaseOrderData, adminUser);

            var logEntries = new List <IActivityLogEntry>
            {
                new PoCreated(cost.CostNumber, purchaseOrderData.PoNumber, adminUser),
                new GoodsReceiptAllocated(cost.CostNumber, purchaseOrderData.GrNumber, adminUser),
                new RequisitionNumber(cost.CostNumber, purchaseOrderData.Requisition, adminUser)
            };

            await _activityLogService.LogRange(logEntries);
        }
Ejemplo n.º 2
0
        private async Task<Dictionary<string, ActionModel>> GetCostActions(UserIdentity userIdentity,
            Cost cost, CostStageRevision costStageRevision, CostUser user)
        {
            var isCostNeverSubmitted = costStageRevision.Status == CostStageRevisionStatus.Draft && costStageRevision.Name == CostStageConstants.OriginalEstimate;

            var stageDetails = JsonConvert.DeserializeObject<PgStageDetailsForm>(costStageRevision.StageDetails?.Data);
            var costUser = new
            {
                isApprover = user.UserUserGroups.Any(uug => uug.UserGroup.ObjectId == cost.Id && uug.UserGroup.Role.Name == Roles.CostApprover),
                isAdmin = user.UserUserGroups.Any(x => x.UserGroup.Role.Name == Roles.ClientAdmin && x.UserGroup.ObjectId == userIdentity.ModuleId),
                authLimit = user.ApprovalLimit,
                isFinanceManager = user.UserBusinessRoles.Any(ubr => ubr.BusinessRole != null && ubr.BusinessRole.Key == Constants.BusinessRole.FinanceManager && (ubr.ObjectId != null || ubr.Labels.Contains(stageDetails.SmoName)))
            };

            var purchaseOrderResponse = _customObjectDataService
                .GetCustomData<PgPurchaseOrderResponse>(costStageRevision.CustomObjectData, CustomObjectDataKeys.PgPurchaseOrderResponse);

            // current user is IPM user and is approved
            var userIsIPMAndApproved = costStageRevision.Approvals
                .Any(s => s.ApprovalMembers.Any(a => a.MemberId == userIdentity.Id && !a.IsExternal && a.Status == ApprovalStatus.Approved));

            var isLatestRevision = cost.LatestCostStageRevisionId == costStageRevision.Id;

            var paymentBelowAuthLimit = true;
            decimal costTotal = 0;

            if (cost.Status != CostStageRevisionStatus.Draft && costUser.authLimit.HasValue)
            {
                costTotal = costStageRevision.CostLineItems.Sum(cli => cli.ValueInDefaultCurrency);
                paymentBelowAuthLimit = costUser.authLimit.Value >= costTotal;
            }

            var actionRule = new PgActionRule
            {
                CostStage = costStageRevision.CostStage.Key,
                Status = costStageRevision.Status.ToString(),
                IsRevision = RevisionStages.Contains(costStageRevision.CostStage.Key),
                IsOwner = cost.OwnerId.Equals(userIdentity.Id),
                IsApprover = costUser.isApprover,
                HasPONumber = !string.IsNullOrEmpty(purchaseOrderResponse?.PoNumber),
                NeverSubmitted = isCostNeverSubmitted,
                HasExternalIntegration = cost.IsExternalPurchases,
                CostStageTotal = costTotal,
                CostTotalBelowAuthLimit = paymentBelowAuthLimit,
                IsAdmin = costUser.isAdmin,
                UserIsIPMAndApproved = userIsIPMAndApproved,
                UserIsFinanceManager = costUser.isFinanceManager,
                IsLatestRevision = isLatestRevision
            };

            var actions = await GetActions(actionRule);
            return actions;
        }
Ejemplo n.º 3
0
        private async Task PopulateOtherFieldsForRecall(EmailNotificationMessage <CostNotificationObject> message, string parent, DateTime timestamp, Guid costId, Guid costStageRevisionId)
        {
            PopulateOtherFields(message, parent, timestamp, costId, costStageRevisionId);

            // Add fields specific to Recall notification message
            var obj           = message.Object;
            var cost          = obj.Cost;
            var stageForm     = _costStageRevisionService.GetStageDetails <PgStageDetailsForm>(costStageRevisionId).Result;
            var buyoutDetails = _costFormService.GetCostFormDetails <BuyoutDetails>(costStageRevisionId).Result;

            cost.AgencyTrackingNumber = stageForm.AgencyTrackingNumber;
            cost.Region          = stageForm.BudgetRegion?.Name;
            cost.AiringCountries = string.Join(";", (buyoutDetails?.AiringCountries ?? new BuyoutDetails.Country[0]).Select(c => c.Name).ToArray());
            cost.Requisition     = (await _customObjectDataService.GetCustomData <PgPurchaseOrderResponse>(costStageRevisionId, CustomObjectDataKeys.PgPurchaseOrderResponse))?.Requisition;
        }
        // TODO cover this logc by unit tests
        private void AddCoupaApprovalEmail(List <EmailNotificationMessage <CostNotificationObject> > notifications,
                                           Cost cost, CostUser costOwner, Guid costStageRevisionId, DateTime timestamp)
        {
            var previousCostStage = _costStageService.GetPreviousCostStage(cost.LatestCostStageRevision.CostStageId).Result;

            if (previousCostStage == null)
            {
                // No need to send COUPA apprvoal email because this is the first time cost gets submitted for Brand Approval
                return;
            }

            var latestRevisionOfPreviousStage = CostStageRevisionService.GetLatestRevision(previousCostStage.Id).Result;

            if (latestRevisionOfPreviousStage == null)
            {
                throw new Exception($"Couldn't find latest revision for stage {previousCostStage.Id}");
            }

            var previousPaymentAmount = _pgPaymentService.GetPaymentAmount(latestRevisionOfPreviousStage.Id, false).Result;
            var currentPaymentAmount  = _pgPaymentService.GetPaymentAmount(costStageRevisionId, false).Result;

            if (currentPaymentAmount.TotalCostAmount == previousPaymentAmount.TotalCostAmount)
            {
                return;
            }

            // Send COUPA approval email because total amount changed
            var paymentDetails = _customObjectDataService.GetCustomData <PgPaymentDetails>(costStageRevisionId, CustomObjectDataKeys.PgPaymentDetails).Result;

            if (!string.IsNullOrEmpty(paymentDetails?.PoNumber))
            {
                var actionType        = core.Constants.EmailNotificationActionType.Submitted;
                var parent            = core.Constants.EmailNotificationParents.Coupa;
                var coupaNotification = new EmailNotificationMessage <CostNotificationObject>(actionType);

                MapEmailNotificationObject(coupaNotification.Object, cost, costOwner);
                PopulateOtherFields(coupaNotification, parent, timestamp, cost.Id, cost.LatestCostStageRevision.Id);
                AddSharedTo(coupaNotification);
                var notificationCost = coupaNotification.Object.Cost;
                notificationCost.PurchaseOrder = new PurchaseOrder();
                Mapper.Map(currentPaymentAmount, notificationCost.PurchaseOrder);
                Mapper.Map(paymentDetails, notificationCost.PurchaseOrder);
                coupaNotification.Parameters.EmailService.AdditionalEmails.Add(AppSettings.CoupaApprovalEmail);

                notifications.Add(coupaNotification);
            }
        }
Ejemplo n.º 5
0
        private async Task <string> GetIoNumberOwner(Guid costStageRevisionId)
        {
            var pgPurchaseOrder = await _customObjectDataService.GetCustomData <PgPaymentDetails>(costStageRevisionId, CustomObjectDataKeys.PgPaymentDetails);

            return(pgPurchaseOrder.IoNumberOwner);
        }
        public async Task <PgLedgerMaterialCodeModel> GetLedgerMaterialCodes(Guid costStageRevisionId)
        {
            var codes = await _customDataService.GetCustomData <PgLedgerMaterialCodeModel>(costStageRevisionId, CustomObjectDataKeys.PgMaterialLedgerCodes);

            return(codes);
        }
        public async Task <PgPurchaseOrder> GetPurchaseOrder(CostStageRevisionStatusChanged stageRevisionStatusChanged)
        {
            var costData = await _efContext.Cost
                           .Include(c => c.LatestCostStageRevision)
                           .ThenInclude(csr => csr.CostStage)
                           .Where(c => c.Id == stageRevisionStatusChanged.AggregateId)
                           .Include(c => c.Parent)
                           .ThenInclude(p => p.Agency)
                           .Select(c => new
            {
                BrandName                 = c.Project.Brand != null ? c.Project.Brand.Name : string.Empty,
                CostNumber                = c.CostNumber,
                CostId                    = c.Id,
                StageDetailsData          = c.LatestCostStageRevision.StageDetails.Data,
                ProductionDetailsData     = c.LatestCostStageRevision.ProductDetails.Data,
                LatestCostStageRevisionId = c.LatestCostStageRevision.Id,
                AgencyLabels              = c.Parent.Agency.Labels,
                CostStageRevisionKey      = c.LatestCostStageRevision.CostStage.Key,
                CostStageRevisionName     = c.LatestCostStageRevision.CostStage.Name,
                Requisitioner             = c.LatestCostStageRevision.Approvals
                                            .Where(a => a.Type == ApprovalType.Brand && a.Requisitioners.Any())
                                            .SelectMany(a => a.Requisitioners)
                                            .Select(r => r.CostUser)
                                            .FirstOrDefault(),
                CostType     = c.CostType,
                ExchangeRate = c.ExchangeRate
            })
                           .FirstOrDefaultAsync();

            if (costData == null)
            {
                _logger.Error($"Couldn't find cost with id {stageRevisionStatusChanged.AggregateId}");
                return(null);
            }

            var purchaseOrderDto = new PgPurchaseOrderDTO
            {
                BrandName                 = costData.BrandName,
                CostNumber                = costData.CostNumber,
                StageDetailsData          = costData.StageDetailsData,
                ProductionDetailsData     = costData.ProductionDetailsData,
                LatestCostStageRevisionId = costData.LatestCostStageRevisionId,
                AgencyLabels              = costData.AgencyLabels,
                CostStageRevisionKey      = costData.CostStageRevisionKey,
                CostStageRevisionName     = costData.CostStageRevisionName,
                RequisitionerEmail        = costData.Requisitioner?.Email,
                TNumber = costData.Requisitioner?.FederationId
            };

            var stageDetailsForm      = JsonConvert.DeserializeObject <PgStageDetailsForm>(purchaseOrderDto.StageDetailsData);
            var productionDetailsForm = purchaseOrderDto.ProductionDetailsData != null?JsonConvert.DeserializeObject <PgProductionDetailsForm>(purchaseOrderDto.ProductionDetailsData) : null;

            var paymentAmount = await GetTotals(stageRevisionStatusChanged.CostStageRevisionId, costData.ExchangeRate);

            var applicableCurrencyCode = await _currencyService.GetCurrencyCode(stageDetailsForm.AgencyCurrency, productionDetailsForm);

            var ledgerMaterialCode = await _ledgerMaterialCode.GetLedgerMaterialCodes(purchaseOrderDto.LatestCostStageRevisionId);

            var purchaseOrderResponse = await _customDataService.GetCustomData <PgPurchaseOrderResponse>(purchaseOrderDto.LatestCostStageRevisionId, CustomObjectDataKeys.PgPurchaseOrderResponse);

            var paymentDetails = await _customDataService.GetCustomData <PgPaymentDetails>(purchaseOrderDto.LatestCostStageRevisionId, CustomObjectDataKeys.PgPaymentDetails);

            var purchaseOrder = new PgPurchaseOrder
            {
                BasketName         = GetBasketName(purchaseOrderDto, stageDetailsForm),
                Description        = GetDescription(purchaseOrderDto, stageDetailsForm),
                TotalAmount        = paymentAmount.TotalAmount,
                PaymentAmount      = paymentAmount.PaymentAmount,
                StartDate          = stageRevisionStatusChanged.TimeStamp,
                CostNumber         = purchaseOrderDto.CostNumber ?? "",
                Currency           = applicableCurrencyCode,
                CategoryId         = ledgerMaterialCode?.MgCode ?? "",
                GL                 = ledgerMaterialCode?.GlCode ?? "",
                DeliveryDate       = GetDeliveryDate(stageRevisionStatusChanged.TimeStamp),
                IONumber           = !string.IsNullOrEmpty(paymentDetails?.IoNumber) ? $"00{paymentDetails.IoNumber}" : "",
                LongText           = GetLongTextField(stageRevisionStatusChanged, purchaseOrderDto, stageDetailsForm, purchaseOrderResponse, paymentAmount.PaymentAmount, applicableCurrencyCode, costData.CostType),
                TNumber            = purchaseOrderDto.TNumber ?? "",
                RequisitionerEmail = purchaseOrderDto.RequisitionerEmail ?? "",
                Vendor             = GetVendor(purchaseOrderDto, productionDetailsForm) ?? "",
                PoNumber           = paymentDetails?.PoNumber ?? "",
                AccountCode        = purchaseOrderResponse?.AccountCode ?? "",
                ItemIdCode         = purchaseOrderResponse?.ItemIdCode ?? "",
                GrNumbers          = await GetGrNumbers(stageRevisionStatusChanged),
                Commodity          = GetCommodity(costData.CostType, stageDetailsForm)
            };

            return(purchaseOrder);
        }