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 UpdateApprovals_ExistingApprovals_ValidBusinessRole_Removed()
        {
            // Arrange
            var existingBusinessRoles = new[] { plugins.Constants.BusinessRole.Ipm, plugins.Constants.BusinessRole.CostConsultant };
            var expectedBusinessRoles = new[] { plugins.Constants.BusinessRole.Ipm };
            var existingApprovals     = new List <Approval>
            {
                new Approval
                {
                    ApprovalMembers    = new List <ApprovalMember>(),
                    Type               = ApprovalType.IPM,
                    Status             = ApprovalStatus.New,
                    ValidBusinessRoles = existingBusinessRoles
                }
            };
            var updatedApprovals = new List <ApprovalModel>
            {
                new ApprovalModel
                {
                    Type               = ApprovalType.IPM,
                    Status             = ApprovalStatus.New,
                    ValidBusinessRoles = expectedBusinessRoles
                }
            };

            SetupRevision(out var user, out var costStageRevisionId, out _, out _, out _);
            _efContext.Approval.AddRange(existingApprovals);
            _efContext.SaveChanges();

            // Act
            await _target.UpdateApprovals(existingApprovals, updatedApprovals, costStageRevisionId, user.Id, user.BuType);

            // Assert
            existingApprovals.Should().NotBeNull();
            existingApprovals[0].ValidBusinessRoles.Should().NotBeNull();
            existingApprovals[0].ValidBusinessRoles.Should().BeEquivalentTo(expectedBusinessRoles);
        }
            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);
            }