public void Setup()
        {
            var approvalServiceMock = new Mock <IApprovalService>();
            var amqSettingsMock     = new Mock <IOptions <AmqSettings> >();

            amqSettingsMock.SetupGet(o => o.Value).Returns(new AmqSettings());
            _efContext = EFContextFactory.CreateInMemoryEFContext();
            var technicalFeeService       = new Mock <ITechnicalFeeService>();
            var revisionPermissionService = new Mock <ICostStageRevisionPermissionService>();
            var costStageRevisionService  = new Mock <ICostStageRevisionService>();

            _costBuilderMock = new Mock <ICostBuilder>();
            var costBuilders = new EditableList <Lazy <ICostBuilder, PluginMetadata> >
            {
                new Lazy <ICostBuilder, PluginMetadata>(
                    () => _costBuilderMock.Object, new PluginMetadata {
                    BuType = BuType.Pg
                })
            };
            var userServiceMock        = new Mock <IUserService>();
            var activityLogServiceMock = new Mock <IActivityLogService>();
            var eventServiceMock       = new Mock <IEventService>();

            _target = new CostApprovalService(approvalServiceMock.Object,
                                              technicalFeeService.Object,
                                              _efContext,
                                              costBuilders,
                                              userServiceMock.Object,
                                              activityLogServiceMock.Object,
                                              eventServiceMock.Object,
                                              revisionPermissionService.Object,
                                              costStageRevisionService.Object
                                              );
        }
            public async Task UpdateApprovalNotRemovingIPMMembersFromPerviousRevision()
            {
                // Arrange
                var costStageRevisionId = Guid.NewGuid();
                var oldRevisionId       = Guid.NewGuid();
                var costId         = Guid.NewGuid();
                var approvalModels = new Builders.Response.ApprovalModel
                {
                    Status = ApprovalStatus.New,
                    Type   = ApprovalType.IPM
                };
                const bool addIpmMember     = true;
                const bool addRequisitioner = false;
                const bool addBrandMember   = false;

                SetupMock(oldRevisionId, addIpmMember, addRequisitioner, addBrandMember, costStageRevisionId, costId, approvalModels);

                // Act
                await CostApprovalService.UpdateApprovals(costId, costStageRevisionId, User, new List <ApprovalModel>());

                // Assert
                var members = await EFContext.Approval.Where(s => s.Type == ApprovalType.IPM && s.CostStageRevisionId == oldRevisionId).Select(a => a.ApprovalMembers).ToListAsync();

                Assert.AreEqual(members.Count, 1);
            }
            public void AddNewApprovals_Fails()
            {
                // Arrange
                var costId = Guid.NewGuid();

                var updateApprovalsModel = CreateUpdateApprovalsModel();

                EFContext.Role.Add(new Role {
                    Id = Guid.NewGuid(), Name = "cost.approver"
                });
                EFContext.CostUser.AddRange(updateApprovalsModel.SelectMany(am => am.ApprovalMembers).Select(m => new CostUser {
                    Id = m.Id
                }));
                EFContext.Cost.Add(new Cost {
                    Id = costId
                });
                EFContext.SaveChanges();

                ApprovalServiceMock.Setup(a => a.GetApprovalsByCostStageRevisionId(It.IsAny <Guid>(), false)).ReturnsAsync(new List <Approval>());

                // Act, Assert
                Assert.ThrowsAsync <InvalidOperationException>(() => CostApprovalService.UpdateApprovals(costId, Guid.Empty, User, updateApprovalsModel));
            }
            public async Task UpdateApprovalAddBrandMembersFromPerviousRevision()
            {
                // Arrange
                var costStageRevisionId = Guid.NewGuid();
                var oldRevisionId       = Guid.NewGuid();
                var costId         = Guid.NewGuid();
                var approvalModels = new Builders.Response.ApprovalModel
                {
                    Status = ApprovalStatus.New,
                    Type   = ApprovalType.Brand
                };
                const bool addIpmMember     = false;
                const bool addRequisitioner = false;
                const bool addBrandMember   = true;

                SetupMock(oldRevisionId, addIpmMember, addRequisitioner, addBrandMember, costStageRevisionId, costId, approvalModels);

                // Act
                await CostApprovalService.UpdateApprovals(costId, costStageRevisionId, User, new List <ApprovalModel>());

                // Assert
                EFContext.Approval.Where(s => s.Type == ApprovalType.Brand && s.CostStageRevisionId == costStageRevisionId).Should().HaveCount(1);
            }
            public async Task UpdateApproval_Always_Should_GrantReadPermissionToNewApprovers()
            {
                // Arrange
                var costStageRevisionId = Guid.NewGuid();
                var oldRevisionId       = Guid.NewGuid();
                var costId                 = Guid.NewGuid();
                var newIPMMemberId         = Guid.NewGuid();
                var newBrandMemberId       = Guid.NewGuid();
                var existingApprovalModels = new Builders.Response.ApprovalModel
                {
                    Status = ApprovalStatus.New,
                    Type   = ApprovalType.IPM
                };
                var newApprovalModels = new List <ApprovalModel>
                {
                    new ApprovalModel
                    {
                        Status          = ApprovalStatus.New,
                        Type            = ApprovalType.IPM,
                        ApprovalMembers = new List <ApprovalModel.Member>
                        {
                            new ApprovalModel.Member
                            {
                                Id = newIPMMemberId
                            }
                        }
                    },
                    new ApprovalModel
                    {
                        Status          = ApprovalStatus.New,
                        Type            = ApprovalType.Brand,
                        ApprovalMembers = new List <ApprovalModel.Member>
                        {
                            new ApprovalModel.Member
                            {
                                Id = newBrandMemberId
                            }
                        }
                    }
                };
                const bool addIpmMember     = true;
                const bool addRequisitioner = false;
                const bool addBrandMember   = true;

                SetupMock(oldRevisionId, addIpmMember, addRequisitioner, addBrandMember, costStageRevisionId, costId, existingApprovalModels);

                EFContext.CostUser.AddRange(new List <CostUser>
                {
                    new CostUser
                    {
                        Id = newIPMMemberId
                    },
                    new CostUser
                    {
                        Id = newBrandMemberId
                    }
                });
                EFContext.SaveChanges();

                // Act
                await CostApprovalService.UpdateApprovals(costId, oldRevisionId, User, newApprovalModels);

                // Assert
                RevisionPermissionService.Verify(rp =>
                                                 rp.GrantCostPermission(costId, Roles.CostViewer, It.Is <IEnumerable <CostUser> >(en => en.Count() == 2), BuType.Pg, It.IsAny <Guid?>(), true),
                                                 Times.Once // One call which includes 2 members: IPM and Brand
                                                 );
            }
            public async Task AddNewApprovalMembers()
            {
                // Arrange
                var costStageRevisionId = Guid.NewGuid();
                var oldRevisionId       = Guid.NewGuid();
                var costId            = Guid.NewGuid();
                var revision          = SetupCostStageRevision(costStageRevisionId, costId, true);
                var existingApprovals = CreateExistingApprovals(revision);

                var updateApprovalsModel = CreateUpdateApprovalsModel();

                EFContext.CostUser.AddRange(updateApprovalsModel.SelectMany(am => am.ApprovalMembers).Select(m => new CostUser
                {
                    Id = m.Id,
                    UserBusinessRoles = new List <UserBusinessRole>
                    {
                        new UserBusinessRole
                        {
                            BusinessRole = new BusinessRole
                            {
                                Key = Constants.BusinessRole.Ipm
                            }
                        },
                        new UserBusinessRole
                        {
                            BusinessRole = new BusinessRole
                            {
                                Key = Constants.BusinessRole.BrandManager
                            }
                        }
                    }
                }));
                EFContext.Approval.AddRange(existingApprovals);

                EFContext.Role.Add(new Role {
                    Id = Guid.NewGuid(), Name = "cost.approver"
                });

                var oldRevision = SetupCostStageRevision(oldRevisionId, costId, true);

                EFContext.CostStageRevision.AddRange(oldRevision);

                ApprovalServiceMock.Setup(a =>
                                          a.GetApprovalsByCostStageRevisionId(It.IsAny <Guid>(), false)
                                          )
                .ReturnsAsync(existingApprovals.Select(a => new Approval
                {
                    Id     = a.Id,
                    Type   = a.Type,
                    Status = a.Status,
                    CostStageRevisionId = a.CostStageRevisionId,
                    CreatedById         = a.CreatedById,
                    ApprovalMembers     = new List <ApprovalMember>(),
                    Requisitioners      = new List <Requisitioner>(),
                    Created             = a.Created,
                    Modified            = a.Modified,
                    ValidBusinessRoles  = a.ValidBusinessRoles
                }).ToList());

                EFContext.Role.Add(new Role {
                    Id = Guid.NewGuid(), Name = "cost.approver"
                });
                EFContext.SaveChanges();

                var ipmApprovalModel = new Builders.Response.ApprovalModel
                {
                    Type = ApprovalType.IPM,
                    ValidBusinessRoles = new [] { Constants.BusinessRole.Ipm }
                };
                var brandApprovalModel = new Builders.Response.ApprovalModel
                {
                    Type = ApprovalType.Brand,
                    ValidBusinessRoles = new [] { Constants.BusinessRole.BrandManager }
                };

                CostBuilderMock.Setup(b =>
                                      b.GetApprovals(It.IsAny <CostType>(), It.IsAny <IStageDetails>(), It.IsAny <Guid>(), costStageRevisionId, costId))
                .ReturnsAsync(new List <Builders.Response.ApprovalModel> {
                    ipmApprovalModel, brandApprovalModel
                });

                // Act
                await CostApprovalService.UpdateApprovals(costId, costStageRevisionId, User, updateApprovalsModel);

                // Assert
                EFContext.Entry(revision).Collection(r => r.Approvals).Load();

                var ipmApproval = await EFContext.Approval
                                  .Include(a => a.ApprovalMembers)
                                  .FirstAsync(a => a.CostStageRevisionId == costStageRevisionId && a.Type == ApprovalType.IPM);

                var brandApproval = await EFContext.Approval
                                    .Include(a => a.ApprovalMembers)
                                    .FirstAsync(a => a.CostStageRevisionId == costStageRevisionId && a.Type == ApprovalType.Brand);

                ipmApproval.ApprovalMembers.Count.Should().Be(1);
                brandApproval.ApprovalMembers.Count.Should().Be(1);
            }