예제 #1
0
        public async Task <List <SupportingDocumentModel> > BuildSupportingDocuments(IStageDetails stageDetails, CostType costType, IEnumerable <string> stageKeys,
                                                                                     Guid costStageRevisionId, bool totalCostIncreased = false)
        {
            var stageDetailsForm = stageDetails.Data.ToModel <PgStageDetailsForm>();

            var rules            = (await _ruleService.GetCompiledByRuleType <SupportingDocumentRule>(RuleType.SupportingDocument)).ToArray();
            var supportingDocs   = new List <SupportingDocumentModel>();
            var previousRevision = await _costStageRevisionService.GetPreviousRevision(costStageRevisionId);

            foreach (var stage in stageKeys)
            {
                var supportingDocRule = new SupportingDocumentRule
                {
                    BudgetRegion       = stageDetailsForm.BudgetRegion?.Key,
                    ContentType        = stageDetailsForm.ContentType?.Key,
                    CostStage          = stage,
                    ProductionType     = stageDetailsForm.ProductionType?.Key,
                    CostType           = costType.ToString(),
                    TotalCostIncreased = totalCostIncreased,
                    PreviousCostStage  = previousRevision != null ? previousRevision?.Name : string.Empty
                };
                List <SupportingDocumentModel> output;
                Func <SupportingDocumentRule, Rule, List <SupportingDocumentModel> > matched = (supportingDocumentRule, rule) =>
                {
                    var ruleDefinition = JsonConvert.DeserializeObject <SupportingDocumentRuleDefinition>(rule.Definition);
                    return(new List <SupportingDocumentModel>
                    {
                        new SupportingDocumentModel
                        {
                            CanManuallyUpload = ruleDefinition.CanManuallyUpload,
                            Name = ruleDefinition.Name,
                            Key = ruleDefinition.Key ?? string.Empty,
                            Generated = true,
                            Required = ruleDefinition.Mandatory
                        }
                    });
                };

                Func <List <SupportingDocumentModel>, List <SupportingDocumentModel>, List <SupportingDocumentModel> > aggregator = (total, result) =>
                {
                    total.AddRange(result);
                    return(total);
                };

                _ruleService.TryMatchRule(rules, supportingDocRule, matched, aggregator, out output);

                if (output != null)
                {
                    supportingDocs.AddRange(output);
                }
            }

            return(supportingDocs);
        }
        public async Task UpdateTechnicalFeeLineItem(Guid costId, Guid latestRevisionId)
        {
            var currentRevision = await _efContext.CostStageRevision
                                  .Include(x => x.Approvals)
                                  .ThenInclude(x => x.ApprovalMembers)
                                  .ThenInclude(x => x.CostUser)
                                  .ThenInclude(x => x.UserBusinessRoles)
                                  .ThenInclude(a => a.BusinessRole)
                                  .FirstOrDefaultAsync(x => x.Id == latestRevisionId);

            var costConsultantApprovals = currentRevision.Approvals?.Where(x =>
                                                                           x.Type == ApprovalType.IPM && x.ValidBusinessRoles?.Contains(Constants.BusinessRole.CostConsultant) == true)
                                          .ToList();

            var costConsultantSelected = costConsultantApprovals
                                         .Any(x => x.ApprovalMembers
                                              .Any(m => m.CostUser.UserBusinessRoles.Any(a => a.BusinessRole.Value == Constants.BusinessRole.CostConsultant)));
            var costLineItems = await _efContext.CostLineItem.Where(x => x.CostStageRevisionId == latestRevisionId).ToListAsync();

            var techFeeLineItem = costLineItems.FirstOrDefault(x => x.Name == Constants.CostSection.TechnicalFee);

            if (techFeeLineItem != null)
            {
                // tech fee is applicable, let's see if we need to recalculate the value
                if (costConsultantSelected && costConsultantApprovals.Any())
                {
                    // currently there is a cost consultant selected

                    var fee = await GetTechnicalFee(costId);

                    if (fee != null && fee.ConsultantRate != 0)
                    {
                        // we got a CC rate, but we only save it if current value is 0
                        if (techFeeLineItem.ValueInDefaultCurrency == 0)
                        {
                            // calculate values based on FX rate
                            var feeCurrency = await _currencyService.GetCurrency(fee.CurrencyCode);

                            if (feeCurrency != null && !feeCurrency.DefaultCurrency)
                            {
                                // only calculate fx rate for foreign currencies
                                var defaultFxRate = await _costExchangeRateService.GetExchangeRateByCurrency(costId, feeCurrency.Id);

                                techFeeLineItem.ValueInDefaultCurrency = fee.ConsultantRate * defaultFxRate.Rate;
                            }
                            else
                            {
                                techFeeLineItem.ValueInDefaultCurrency = fee.ConsultantRate;
                            }

                            var localCurrency = await _currencyService.GetCurrency(techFeeLineItem.LocalCurrencyId);

                            if (localCurrency != null && !localCurrency.DefaultCurrency)
                            {
                                var localFxRate = await _costExchangeRateService.GetExchangeRateByCurrency(costId, techFeeLineItem.LocalCurrencyId);

                                techFeeLineItem.ValueInLocalCurrency = techFeeLineItem.ValueInDefaultCurrency / localFxRate.Rate; // reverse conversion
                            }
                            else
                            {
                                techFeeLineItem.ValueInLocalCurrency = techFeeLineItem.ValueInDefaultCurrency;
                            }


                            _efContext.Update(techFeeLineItem);
                            await _efContext.SaveChangesAsync();
                        }
                    }
                }
                else if (techFeeLineItem.ValueInDefaultCurrency > 0)
                {
                    // cost consultant is not selected, but there is a fee - let's set the rate to 0 if previously we don't have any approved revisions/stages with tech fee

                    var previousRevision = await _costStageRevisionService.GetPreviousRevision(currentRevision.Id);

                    if (previousRevision != null)
                    {
                        var previousCostLineItems = await _costStageRevisionService.GetCostLineItems(previousRevision.Id);

                        var prevTechFeeLineItem = previousCostLineItems.FirstOrDefault(x => x.Name == Constants.CostSection.TechnicalFee);

                        if (prevTechFeeLineItem == null || prevTechFeeLineItem.ValueInDefaultCurrency == 0)
                        {
                            // we don't have a value - let's set it to 0
                            await SetToZeroAndSave(techFeeLineItem);
                        }
                    }
                    else
                    {
                        // we don't have a previous review - let's set it to 0
                        await SetToZeroAndSave(techFeeLineItem);
                    }
                }
            }
        }