From bf3db2b93afaa5c60c9cec0991e397b6f653ba3c Mon Sep 17 00:00:00 2001 From: Daniel Bisgrove Date: Wed, 16 Sep 2026 14:19:30 -0400 Subject: [PATCH] [MPDX-10017] Show the requested gross salary on the pending request card The pending salary request card was labelled "Gross Salary Requested" but rendered the HCM current salary, which is the person's existing payroll amount and unrelated to the request they submitted. Fetch `calculations.requestedGross` on the latest salary request and render that instead. This is the same server-computed field the "Gross Requested Salary" total row of RequestSummaryCard uses, so the landing card and the request itself can no longer disagree. Also orient the latest calculation to the user's perspective before reading its amounts, as the landing page already does for the effective calculation. Without this, a request created by the spouse showed the spouse's figures. --- .../LandingSalaryCalculations.graphql | 7 +++ .../LandingTestWrapper.tsx | 9 +++ .../PendingRequestCard.test.tsx | 62 +++++++++++++++++-- .../PendingRequestCard.tsx | 60 +++++++++++++----- .../components/PendingRequestActions.test.tsx | 3 + .../PendingRequestTimeline.test.tsx | 3 + .../Landing/useLandingData.ts | 9 ++- 7 files changed, 131 insertions(+), 22 deletions(-) diff --git a/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingSalaryCalculations.graphql b/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingSalaryCalculations.graphql index 2c0ba6af82..2db0b4e77c 100644 --- a/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingSalaryCalculations.graphql +++ b/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingSalaryCalculations.graphql @@ -4,6 +4,7 @@ query LandingSalaryCalculations { ) { id status + personNumber salary spouseSalary mhaAmount @@ -11,6 +12,12 @@ query LandingSalaryCalculations { submittedAt changesRequestedAt feedback + calculations { + requestedGross + } + spouseCalculations { + requestedGross + } } inProgressCalculation: latestSalaryRequest(status: [IN_PROGRESS]) { id diff --git a/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingTestWrapper.tsx b/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingTestWrapper.tsx index 7357ecc202..b4a6e51639 100644 --- a/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingTestWrapper.tsx +++ b/src/components/HrTools/SalaryCalculator/Landing/NewSalaryCalculationLanding/LandingTestWrapper.tsx @@ -26,6 +26,7 @@ export interface LandingTestWrapperProps { hasApprovedCalculation?: boolean; hasSpouseApprovedCalculation?: boolean; hasLatestCalculation?: boolean; + hasSpouseLatestCalculation?: boolean; salaryRequestEligible?: boolean; } @@ -36,6 +37,7 @@ export const LandingTestWrapper: React.FC = ({ hasApprovedCalculation = false, hasSpouseApprovedCalculation = false, hasLatestCalculation = false, + hasSpouseLatestCalculation = false, salaryRequestEligible = true, }) => ( @@ -116,9 +118,16 @@ export const LandingTestWrapper: React.FC = ({ ? { id: 'pending-calc-1', status: SalaryRequestStatusEnum.Pending, + personNumber: hasSpouseLatestCalculation + ? '000123457' + : '000123456', + salary: 52000, + spouseSalary: 51000, submittedAt: '2025-01-16T10:00:00Z', changesRequestedAt: null, feedback: null, + calculations: { requestedGross: 69714.29 }, + spouseCalculations: { requestedGross: 62000 }, } : null, }, diff --git a/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.test.tsx b/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.test.tsx index 78381290e5..315b45b900 100644 --- a/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.test.tsx +++ b/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.test.tsx @@ -1,10 +1,13 @@ import React from 'react'; -import { render } from '@testing-library/react'; -import { LandingTestWrapper } from '../NewSalaryCalculationLanding/LandingTestWrapper'; +import { render, waitFor } from '@testing-library/react'; +import { + LandingTestWrapper, + LandingTestWrapperProps, +} from '../NewSalaryCalculationLanding/LandingTestWrapper'; import { PendingRequestCard } from './PendingRequestCard'; -const TestComponent: React.FC = () => ( - +const TestComponent: React.FC = (props) => ( + ); @@ -19,6 +22,57 @@ describe('PendingRequestCard', () => { ).toBeInTheDocument(); }); + it('renders the requested gross salary, not the current gross salary', async () => { + const { getByTestId } = render(); + + await waitFor(() => + expect(getByTestId('gross-salary-amount')).toHaveTextContent( + '$69,714.29', + ), + ); + }); + + it("renders the spouse's requested gross salary alongside the user's", async () => { + const { getByTestId, getByText } = render(); + + await waitFor(() => + expect(getByTestId('spouse-gross-salary-amount')).toHaveTextContent( + '$62,000.00', + ), + ); + expect(getByText('John')).toBeInTheDocument(); + expect(getByText('Jane')).toBeInTheDocument(); + }); + + it('swaps the amounts when the spouse created the request', async () => { + const { getByTestId } = render( + , + ); + + await waitFor(() => + expect(getByTestId('gross-salary-amount')).toHaveTextContent( + '$62,000.00', + ), + ); + expect(getByTestId('spouse-gross-salary-amount')).toHaveTextContent( + '$69,714.29', + ); + }); + + it('renders a single amount and no names when there is no spouse', async () => { + const { getByTestId, queryByTestId, queryByText } = render( + , + ); + + await waitFor(() => + expect(getByTestId('gross-salary-amount')).toHaveTextContent( + '$69,714.29', + ), + ); + expect(queryByTestId('spouse-gross-salary-amount')).not.toBeInTheDocument(); + expect(queryByText('John')).not.toBeInTheDocument(); + }); + it('renders print link with correct href', async () => { const { findByRole } = render(); diff --git a/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.tsx b/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.tsx index e593a0b705..1f76213774 100644 --- a/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.tsx +++ b/src/components/HrTools/SalaryCalculator/Landing/PendingSalaryCalculationLanding/PendingRequestCard.tsx @@ -6,6 +6,7 @@ import { Card, CardContent, CardHeader, + Grid, IconButton, Typography, } from '@mui/material'; @@ -21,16 +22,19 @@ import { PendingRequestTimeline } from './components/PendingRequestTimeline'; export const PendingRequestCard: React.FC = () => { const { t } = useTranslation(); const accountListId = useAccountListId(); - const { - calculation, - requestedOn, - processedOn, - feedback, - salaryData: { currentGrossSalary }, - } = useLandingData(); + const { calculation, self, spouse, requestedOn, processedOn, feedback } = + useLandingData(); const locale = useLocale(); + // The gross request is the requested salary plus SECA and 403(b) contributions + const requestedGross = calculation?.calculations?.requestedGross ?? 0; + const spouseRequestedGross = calculation?.spouseCalculations?.requestedGross; + const hasSpouse = !!spouse && spouseRequestedGross !== undefined; + + const formatGross = (amount: number) => + currencyFormat(amount, 'USD', locale, { showTrailingZeros: true }); + return ( { > {t('Gross Salary Requested')?.toUpperCase()} - - {currencyFormat(currentGrossSalary, 'USD', locale, { - showTrailingZeros: true, - })} - + + + {hasSpouse && ( + + {self?.staffInfo.preferredName} + + )} + + {formatGross(requestedGross)} + + + {hasSpouse && ( + + + {spouse.staffInfo.preferredName} + + + {formatGross(spouseRequestedGross)} + + + )} + ({ id: '1', status, + personNumber: '000123456', mhaAmount: null, spouseMhaAmount: null, salary: null, @@ -22,6 +23,8 @@ const createCalculation = ( submittedAt: '2025-01-15T10:00:00Z', changesRequestedAt: null, feedback, + calculations: { requestedGross: 0 }, + spouseCalculations: null, }); interface TestComponentProps { diff --git a/src/components/HrTools/SalaryCalculator/Landing/useLandingData.ts b/src/components/HrTools/SalaryCalculator/Landing/useLandingData.ts index 0ea4b97080..790c4a28e8 100644 --- a/src/components/HrTools/SalaryCalculator/Landing/useLandingData.ts +++ b/src/components/HrTools/SalaryCalculator/Landing/useLandingData.ts @@ -96,6 +96,13 @@ export const useLandingData = (): LandingData => { }; }, [hcmData]); + // The latest calculation may have been created by the spouse, so orient it to the user's + // perspective before exposing its amounts + const calculation = useMemo( + () => orientSalaryRequest(latestCalculation, self?.staffInfo.personNumber), + [latestCalculation, self], + ); + const staffAccountId = useMemo( () => staffAccountIdData?.user?.staffAccountId ?? null, [staffAccountIdData], @@ -264,7 +271,7 @@ export const useLandingData = (): LandingData => { calculationLoading || accountBalanceLoading || staffAccountIdLoading, - calculation: latestCalculation, + calculation, requestedOn, processedOn, feedback,