diff --git a/api/app/src/Controller/UserController.php b/api/app/src/Controller/UserController.php index d3efceba5c..ed90250337 100755 --- a/api/app/src/Controller/UserController.php +++ b/api/app/src/Controller/UserController.php @@ -40,7 +40,7 @@ public function __construct( private EntityManagerInterface $em, private AuthService $authService, private RestFormatter $formatter, - private PasswordHasherFactoryInterface $hasherFactory + private PasswordHasherFactoryInterface $hasherFactory, ) { } @@ -651,4 +651,18 @@ public function getPrimaryEmail(int $deputyUid): string return $userEmail; } + + /** + * Endpoint for getting the primary user account associated with a deputy uid. + * + * @Route("/get-primary-user-account/{deputyUid}", methods={"GET"}) + * + * @throws \Exception + */ + public function getPrimaryUserAccount(int $deputyUid): ?User + { + $this->formatter->setJmsSerialiserGroups(['user', 'user-list']); + + return $this->userRepository->findPrimaryUserByDeputyUid($deputyUid); + } } diff --git a/api/app/src/DataFixtures/TestUserFixtures.php b/api/app/src/DataFixtures/TestUserFixtures.php index 5501576f9e..5e4c63ba1e 100644 --- a/api/app/src/DataFixtures/TestUserFixtures.php +++ b/api/app/src/DataFixtures/TestUserFixtures.php @@ -17,6 +17,7 @@ class TestUserFixtures extends AbstractDataFixture 'id' => 'multi-client-primary-deputy', 'roleName' => 'ROLE_LAY_DEPUTY', 'deputyUid' => 567890098765, + 'isPrimary' => true, ], [ 'id' => 'multi-client-non-primary-deputy', @@ -87,7 +88,8 @@ private function addUser($data, $manager) ->setAddressCountry('GB') ->setRoleName($data['roleName']) ->setDeputyUid($data['deputyUid'] ?? null) - ->setCoDeputyClientConfirmed($data['co-deputy'] ?? false); + ->setCoDeputyClientConfirmed($data['co-deputy'] ?? false) + ->setIsPrimary($data['isPrimary'] ?? false); $manager->persist($user); } diff --git a/api/app/src/v2/DTO/UserDto.php b/api/app/src/v2/DTO/UserDto.php index 84c0d61296..dedca5e137 100644 --- a/api/app/src/v2/DTO/UserDto.php +++ b/api/app/src/v2/DTO/UserDto.php @@ -52,6 +52,10 @@ class UserDto /** @var array */ private $clients; + private ?int $deputyUid; + + private bool $isPrimary; + public function getId(): int { return $this->id; @@ -275,4 +279,28 @@ public function setAddressCountry(?string $addressCountry): UserDto return $this; } + + public function getDeputyUid(): ?int + { + return $this->deputyUid ?? null; + } + + public function setDeputyUid(?int $deputyUid): UserDto + { + $this->deputyUid = $deputyUid; + + return $this; + } + + public function getIsPrimary(): ?bool + { + return $this->isPrimary; + } + + public function setIsPrimary(?bool $isPrimary): UserDto + { + $this->isPrimary = $isPrimary; + + return $this; + } } diff --git a/api/app/src/v2/Transformer/ClientTransformer.php b/api/app/src/v2/Transformer/ClientTransformer.php index cced279cd7..cdeb6bf124 100644 --- a/api/app/src/v2/Transformer/ClientTransformer.php +++ b/api/app/src/v2/Transformer/ClientTransformer.php @@ -22,7 +22,7 @@ class ClientTransformer public function __construct( ReportTransformer $reportTransformer, NdrTransformer $ndrTransformer, - DeputyTransformer $deputyTransformer + DeputyTransformer $deputyTransformer, ) { $this->reportTransformer = $reportTransformer; $this->ndrTransformer = $ndrTransformer; @@ -146,6 +146,8 @@ private function transformDeputies(array $userDtos) 'job_title' => $userDto->getJobTitle(), 'phone_main' => $userDto->getPhoneMain(), 'last_logged_in' => $userDto->getLastLoggedIn() instanceof \DateTime ? $userDto->getLastLoggedIn()->format('Y-m-d H:i:s') : null, + 'deputy_uid' => $userDto->getDeputyUid(), + 'is_primary' => $userDto->getIsPrimary(), ]; } } diff --git a/api/app/tests/Behat/bootstrap/v2/ClientManagement/ClientManagementTrait.php b/api/app/tests/Behat/bootstrap/v2/ClientManagement/ClientManagementTrait.php index cf8f803f1b..4df48b3924 100644 --- a/api/app/tests/Behat/bootstrap/v2/ClientManagement/ClientManagementTrait.php +++ b/api/app/tests/Behat/bootstrap/v2/ClientManagement/ClientManagementTrait.php @@ -222,6 +222,39 @@ public function iShouldSeeLayDeputyDetails() } } + /** + * @Then I should see the Primary Lay deputies name, address and contact details + */ + public function iShouldSeePrimaryLayDeputyDetails() + { + $pageContent = $this->getSession()->getPage()->find('css', 'main#main-content')->getHtml(); + + $detailsToAssertOn[] = $this->layPfaHighNotStartedMultiClientDeputyPrimaryUser->getUserFullname(); + $detailsToAssertOn[] = $this->layPfaHighNotStartedMultiClientDeputyPrimaryUser->getUserPhone(); + $detailsToAssertOn[] = $this->layPfaHighNotStartedMultiClientDeputyPrimaryUser->getUserEmail(); + $detailsToAssertOn = array_merge( + $detailsToAssertOn, + $this->layPfaHighNotStartedMultiClientDeputyPrimaryUser->getUserFullAddressArray() + ); + + $missingDetails = []; + + foreach ($detailsToAssertOn as $detail) { + $detailPresent = str_contains($pageContent, $detail); + + if (!$detailPresent) { + $missingDetails[] = $detail; + } + } + + if (!empty($missingDetails)) { + $missingDetailsString = implode(', ', $missingDetails); + $detailsToAssertOnString = implode(', ', $detailsToAssertOn); + + throw new BehatException(sprintf('Some client details were missing: %s. Wanted: %s, got (full HTML): %s', $missingDetailsString, $detailsToAssertOnString, $pageContent)); + } + } + /** * @Then I should see the reports associated with the client */ diff --git a/api/app/tests/Behat/bootstrap/v2/Common/IVisitAdminTrait.php b/api/app/tests/Behat/bootstrap/v2/Common/IVisitAdminTrait.php index 289c854ed9..3a425f5ba7 100644 --- a/api/app/tests/Behat/bootstrap/v2/Common/IVisitAdminTrait.php +++ b/api/app/tests/Behat/bootstrap/v2/Common/IVisitAdminTrait.php @@ -34,6 +34,21 @@ public function iVisitAdminLayClientDetailsPage() $this->interactingWithUserDetails = $this->layDeputySubmittedPfaHighAssetsDetails; } + /** + * @When I visit the admin client details page for an existing client linked to a non-primary Lay deputy user account + */ + public function iVisitAdminLayClientDetailsPageForNonPrimaryDeputy() + { + if (!in_array($this->loggedInUserDetails->getUserRole(), $this->loggedInUserDetails::ADMIN_ROLES)) { + throw new BehatException('Attempting to access an admin page as a non-admin user. Try logging in as an admin user instead'); + } + + $clientDetailsUrl = $this->getAdminClientDetailsUrl($this->layPfaHighNotStartedMultiClientDeputyNonPrimaryUser->getClientId()); + $this->visitAdminPath($clientDetailsUrl); + + $this->interactingWithUserDetails = $this->layPfaHighNotStartedMultiClientDeputyNonPrimaryUser; + } + /** * @When I visit the admin client archived page for the user I'm interacting with */ diff --git a/api/app/tests/Behat/features-v2/client-management/admin/view-client.feature b/api/app/tests/Behat/features-v2/client-management/admin/view-client.feature index 427491a58b..c3af8d5253 100644 --- a/api/app/tests/Behat/features-v2/client-management/admin/view-client.feature +++ b/api/app/tests/Behat/features-v2/client-management/admin/view-client.feature @@ -24,3 +24,12 @@ Feature: Admin - View client details Given a super admin user accesses the admin app When I visit the admin client details page for an existing client linked to a Lay deputy And I should see "Discharge deputy" + + @admin @lay-pfa-high-not-started-multi-client-deputy + Scenario: An admin user views client details associated with a non-primary Lay deputy user account + Given an admin user accesses the admin app + When I visit the admin client details page for an existing client linked to a non-primary Lay deputy user account + Then I should see the clients court order number + And I should see the Primary Lay deputies name, address and contact details + And I should see the reports associated with the client + And I should not see "Discharge deputy" diff --git a/api/app/tests/Unit/Controller/UserControllerTest.php b/api/app/tests/Unit/Controller/UserControllerTest.php index f9758c8f59..c9c657038f 100644 --- a/api/app/tests/Unit/Controller/UserControllerTest.php +++ b/api/app/tests/Unit/Controller/UserControllerTest.php @@ -12,6 +12,8 @@ class UserControllerTest extends AbstractTestController private static $deputy1; private static $admin1; private static $deputy2; + private static $primaryUserAccount; + private static $nonPrimaryUserAccount; private static $tokenAdmin; private static $tokenSuperAdmin; private static $tokenDeputy; @@ -29,6 +31,8 @@ public function setUp(): void self::$deputy1 = self::fixtures()->getRepo('User')->findOneByEmail('deputy@example.org'); self::$admin1 = self::fixtures()->getRepo('User')->findOneByEmail('admin@example.org'); self::$deputy2 = self::fixtures()->createUser(); + self::$primaryUserAccount = self::fixtures()->getRepo('User')->findOneByEmail('multi-client-primary-deputy@example.org'); + self::$nonPrimaryUserAccount = self::fixtures()->getRepo('User')->findOneByEmail('multi-client-non-primary-deputy@example.org'); self::fixtures()->flush()->clear(); } @@ -545,4 +549,19 @@ public function testAgreeTermsUse() $this->assertTrue($deputy->getAgreeTermsUse()); $this->assertEquals(date('Y-m-d'), $deputy->getAgreeTermsUseDate()->format('Y-m-d')); } + + public function testGetPrimaryAccount() + { + $url = '/user/get-primary-user-account/567890098765'; + + $data = $this->assertJsonRequest('GET', $url, [ + 'mustSucceed' => true, + 'assertResponseCode' => 200, + 'AuthToken' => self::$tokenAdmin, + ])['data']; + + $this->assertEquals('multi-client-primary-deputy', $data['lastname']); + $this->assertEquals('multi-client-primary-deputy@example.org', $data['email']); + $this->assertTrue($data['is_primary']); + } } diff --git a/client/app/src/Controller/Admin/Client/ClientController.php b/client/app/src/Controller/Admin/Client/ClientController.php index e1b27dcd86..b845ddf2e2 100644 --- a/client/app/src/Controller/Admin/Client/ClientController.php +++ b/client/app/src/Controller/Admin/Client/ClientController.php @@ -3,8 +3,10 @@ namespace App\Controller\Admin\Client; use App\Controller\AbstractController; +use App\Entity\User; use App\Service\Audit\AuditEvents; use App\Service\Client\Internal\ClientApi; +use App\Service\Client\Internal\UserApi; use App\Service\Client\RestClient; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; @@ -16,18 +18,11 @@ */ class ClientController extends AbstractController { - /** @var RestClient */ - private $restClient; - - /** @var ClientApi */ - private $clientApi; - public function __construct( - RestClient $restClient, - ClientApi $clientApi + private RestClient $restClient, + private ClientApi $clientApi, + private UserApi $userApi, ) { - $this->restClient = $restClient; - $this->clientApi = $clientApi; } /** @@ -47,9 +42,17 @@ public function detailsAction($id) return $this->redirectToRoute('admin_client_archived', ['id' => $client->getId()]); } + $deputy = $client->getDeputy(); + + if ($deputy instanceof User) { + if (false == $deputy->getIsPrimary()) { + $deputy = $this->userApi->getPrimaryUserAccount($deputy->getDeputyUid()); + } + } + return [ 'client' => $client, - 'deputy' => $client->getDeputy(), + 'deputy' => $deputy, ]; } diff --git a/client/app/src/Service/Client/Internal/UserApi.php b/client/app/src/Service/Client/Internal/UserApi.php index caecefdc87..f1ce2b2b18 100644 --- a/client/app/src/Service/Client/Internal/UserApi.php +++ b/client/app/src/Service/Client/Internal/UserApi.php @@ -32,7 +32,7 @@ class UserApi protected const DEPUTY_SELF_REGISTER_ENDPOINT = 'selfregister'; protected const CREATE_CODEPUTY_ENDPOINT = 'codeputy/add/%s'; protected const CLEAR_REGISTRATION_TOKEN_ENDPOINT = 'user/clear-registration-token/%s'; - + protected const GET_PRIMARY_USER_ACCOUNT_ENDPOINT = 'user/get-primary-user-account/%s'; protected const GET_PRIMARY_EMAIL = 'user/get-primary-email/%s'; /** @var RestClientInterface */ @@ -47,7 +47,7 @@ class UserApi public function __construct( RestClientInterface $restClient, TokenStorageInterface $tokenStorage, - ObservableEventDispatcher $eventDispatcher + ObservableEventDispatcher $eventDispatcher, ) { $this->restClient = $restClient; $this->tokenStorage = $tokenStorage; @@ -277,4 +277,13 @@ public function returnPrimaryEmail(int $deputyUid): string return json_decode($jsonString, true)['data']; } + + public function getPrimaryUserAccount(int $deputyUid): User + { + return $this->restClient->get( + sprintf(self::GET_PRIMARY_USER_ACCOUNT_ENDPOINT, $deputyUid), + 'User', + [] + ); + } }