public void When_StageSplitIs_Zero_Or_One_ShouldNotThrowException(decimal split)
            {
                // Arrange
                var rule = new PgVendorRuleDefinition
                {
                    Splits = new[]
                    {
                        new PgVendorRuleSplit
                        {
                            CostTotalType = Constants.CostSection.CostTotal,
                            StageSplits   = new Dictionary <string, decimal?>
                            {
                                { CostStages.FinalActual.ToString(), split }
                            }
                        }
                    }
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr)
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                // Act, Assert
                _pgVendorRuleBuilder
                .Awaiting(b => b.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>()))
                .ShouldNotThrow <Exception>();
            }
            public void ThrowException_When_CriterionIsSelectAndValueIsInvalid2()
            {
                // Arrange
                var costTotalType = "Anything else";

                var rule = new PgVendorRuleDefinition
                {
                    Splits = new[]
                    {
                        new PgVendorRuleSplit
                        {
                            CostTotalType = costTotalType,
                            StageSplits   = new Dictionary <string, decimal?>()
                        }
                    }
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr)
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                // Act, Assert
                _pgVendorRuleBuilder
                .Awaiting(b => b.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>()))
                .ShouldThrow <Exception>()
                .WithMessage($"Unsupported Cost Total Type {costTotalType}");
            }
            public void ThrowException_When_CriterionNameIsInvalid()
            {
                // Arrange
                const string criteriaName = "unsupported criterion";
                var          rule         = new PgVendorRuleDefinition
                {
                    Splits = new PgVendorRuleSplit[0]
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr),
                    Criteria   = new Dictionary <string, CriterionValueModel>
                    {
                        { criteriaName, new CriterionValueModel() }
                    }
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                MockCriteria();

                // Act
                // Assert
                _pgVendorRuleBuilder
                .Awaiting(b => b.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>()))
                .ShouldThrow <Exception>()
                .WithMessage($"Unsupported criterion {criteriaName}");
            }
            public void ThrowException_When_CriterionIsSelectAndValueIsInvalid()
            {
                // Arrange
                const string validCriteriaName = nameof(Constants.DictionaryNames.ContentType);
                const string wrongValue        = "not existing value";
                var          rule = new PgVendorRuleDefinition
                {
                    Splits = new PgVendorRuleSplit[0]
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr),
                    Criteria   = new Dictionary <string, CriterionValueModel>
                    {
                        { validCriteriaName, new CriterionValueModel {
                              Value = wrongValue
                          } }
                    }
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                MockCriteria();

                // Act
                // Assert
                _pgVendorRuleBuilder
                .Awaiting(b => b.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>()))
                .ShouldThrow <Exception>()
                .WithMessage($"Unsupported value {wrongValue} of {validCriteriaName} criterion");
            }
            public async Task DetailedSplit_When_SingleSplit_And_CostsTotal_ShouldBeFalse()
            {
                // Arrange
                var rule = new PgVendorRuleDefinition
                {
                    Splits = new[]
                    {
                        new PgVendorRuleSplit
                        {
                            CostTotalType = Constants.CostSection.CostTotal,
                            StageSplits   = new Dictionary <string, decimal?>
                            {
                                { CostStages.FinalActual.ToString(), (decimal)1.0 }
                            }
                        }
                    }
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr)
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                // Act
                var result = await _pgVendorRuleBuilder.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>());

                var parsedResult = JsonConvert.DeserializeObject <PgPaymentRuleDefinition>(result.First().Rule.Definition);

                // Assert
                parsedResult.DetailedSplit.Should().BeFalse();
            }
            public async Task Always_Should_MapStageSplitsCorrectly()
            {
                // Arrange
                const decimal aipeSplit = 0.1m;
                const decimal oeSplit   = 0.2m;
                const decimal fpSplit   = 0.3m;
                const decimal faSplit   = 1.0m;

                var rule = new PgVendorRuleDefinition
                {
                    Splits = new[]
                    {
                        new PgVendorRuleSplit
                        {
                            CostTotalType = Constants.CostSection.TargetBudgetTotal,
                            StageSplits   = new Dictionary <string, decimal?>
                            {
                                { CostStages.Aipe.ToString(), aipeSplit },
                                { CostStages.OriginalEstimate.ToString(), oeSplit },
                                { CostStages.FirstPresentation.ToString(), fpSplit },
                                { CostStages.FinalActual.ToString(), faSplit }
                            }
                        }
                    }
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr)
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                // Act
                var result = await _pgVendorRuleBuilder.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>());

                var parsedResult = JsonConvert.DeserializeObject <PgPaymentRuleDefinition>(result.First().Rule.Definition);

                // Assert
                parsedResult.Splits.Should().HaveCount(1);
                parsedResult.Splits[0].AIPESplit.Should().Be(aipeSplit);
                parsedResult.Splits[0].OESplit.Should().Be(oeSplit);
                parsedResult.Splits[0].FPSplit.Should().Be(fpSplit);
                parsedResult.Splits[0].FASplit.Should().Be(faSplit);
            }
            public async Task SkipFirstStagePresentation_When_SkipFirstPresentation_ShouldAddSkipFirstPresentationStageRule()
            {
                // Arrange
                var rule = new PgVendorRuleDefinition
                {
                    Splits = new PgVendorRuleSplit[0]
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name                  = "Vendor payment rule 1",
                    Definition            = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr),
                    SkipFirstPresentation = true
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };
                var skipFirstPresentationRule = new Rule
                {
                    Name       = Constants.Rules.Stage.SkipFirstPresentation,
                    Type       = RuleType.Stage,
                    Definition = JsonConvert.SerializeObject(new PgStageRuleDefinition())
                };

                _efContext.Rule.Add(skipFirstPresentationRule);
                _efContext.SaveChanges();

                // Act
                var vendorRules = await _pgVendorRuleBuilder.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>());

                var parsedResults = vendorRules.Select(r =>
                                                       JsonConvert.DeserializeObject <PgPaymentRuleDefinition>(r.Rule.Definition))
                                    .ToArray();

                //Assert
                parsedResults.Should().HaveCount(2);
                vendorRules.Count(r => r.Rule.Type == RuleType.VendorStage).Should().Be(1);
                vendorRules.Count(r => r.Rule.Type == RuleType.VendorPayment).Should().Be(1);
                var stageRule = vendorRules.First(vr => vr.Rule.Type == RuleType.VendorStage);

                stageRule.Rule.Definition.Should().Be(skipFirstPresentationRule.Definition);
            }
            public async Task When_StageSplitIsNotListedInSplits_Should_DefaultSplitToZero()
            {
                // Arrange
                const decimal faSplit = 1.0m;

                var rule = new PgVendorRuleDefinition
                {
                    Splits = new[]
                    {
                        new PgVendorRuleSplit
                        {
                            CostTotalType = Constants.CostSection.TargetBudgetTotal,
                            StageSplits   = new Dictionary <string, decimal?>
                            {
                                { CostStages.FinalActual.ToString(), faSplit }
                            }
                        }
                    }
                };
                var ruleStr  = JsonConvert.SerializeObject(rule);
                var ruleMode = new VendorRuleModel
                {
                    Name       = "Vendor payment rule 1",
                    Definition = JsonConvert.DeserializeObject <Dictionary <string, dynamic> >(ruleStr)
                };
                var vendor = new Vendor {
                    Name = "Vendor 1"
                };

                // Act
                var result = await _pgVendorRuleBuilder.ValidateAndGetVendorRules(ruleMode, vendor, It.IsAny <Guid>());

                var parsedResult = JsonConvert.DeserializeObject <PgPaymentRuleDefinition>(result.First().Rule.Definition);

                // Assert
                parsedResult.Splits.Should().HaveCount(1);
                parsedResult.Splits[0].AIPESplit.Should().Be(0m);
                parsedResult.Splits[0].OESplit.Should().Be(0m);
                parsedResult.Splits[0].FPSplit.Should().Be(0m);
                parsedResult.Splits[0].FASplit.Should().Be(faSplit);
            }