Skip to content

Commit

Permalink
Merge branch 'staging' into opex-get-case-data-for-qgis
Browse files Browse the repository at this point in the history
  • Loading branch information
jimlerza committed Nov 24, 2024
2 parents 3d4fcf9 + 7c03937 commit f52f423
Show file tree
Hide file tree
Showing 50 changed files with 668 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('File a petition: Step 1 - Petitioner Information', () => {
cy.get('[data-testid="filing-type-0"]').click();
cy.get('[data-testid="contact-primary-name-label"]').should(
'have.text',
'Full Name',
'Full name',
);
});

Expand Down
14 changes: 14 additions & 0 deletions shared/src/business/entities/trialSessions/SpecialTrialSessions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export type SpecialTrialSession = {
userId: string;
trialSessionId: string;
};

export type SpecialTrialSessionKey = {
pk: string;
sk: string;
};

export type TrialSessionWorkingCopyNotes = {
sessionNotes: string;
trialSessionId: string;
};
51 changes: 51 additions & 0 deletions shared/src/business/useCases/getCaseInteractor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,57 @@ describe('getCaseInteractor', () => {
expect(result.docketNumber).toEqual('101-00');
});

it('should filter out docket entries that are not on the docket record when the currentUser is an external user associated with an unsealed case', async () => {
const expectedDocketEntries = testCase.docketEntries.filter(
de => de.isOnDocketRecord,
);
applicationContext
.getPersistenceGateway()
.getCaseByDocketNumber.mockResolvedValue(testCase);

const result = await getCaseInteractor(
applicationContext,
{
docketNumber: testCase.docketNumber,
},
{
email: mockCaseContactPrimary.email,
name: mockCaseContactPrimary.name,
role: ROLES.petitioner,
userId: mockCaseContactPrimary.contactId,
},
);

expect(result.docketEntries).toMatchObject(expectedDocketEntries);
});

it('should filter out docket entries that are not on the docket record when the currentUser is an external user associated with a sealed case', async () => {
const expectedDocketEntries = testCase.docketEntries.filter(
de => de.isOnDocketRecord,
);
applicationContext
.getPersistenceGateway()
.getCaseByDocketNumber.mockResolvedValue({
...testCase,
isSealed: true,
});

const result = await getCaseInteractor(
applicationContext,
{
docketNumber: testCase.docketNumber,
},
{
email: mockCaseContactPrimary.email,
name: mockCaseContactPrimary.name,
role: ROLES.petitioner,
userId: mockCaseContactPrimary.contactId,
},
);

expect(result.docketEntries).toMatchObject(expectedDocketEntries);
});

it('should return the case when the currentUser is an irs superuser even if the case has sealed documents', async () => {
applicationContext
.getPersistenceGateway()
Expand Down
24 changes: 24 additions & 0 deletions shared/src/business/useCases/getCaseInteractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import {
isAssociatedUser,
isUserPartOfGroup,
} from '../entities/cases/Case';
import {
INITIAL_DOCUMENT_TYPES,
ROLES,
} from '@shared/business/entities/EntityConstants';
import { NotFoundError, UnauthorizedError } from '@web-api/errors/errors';
import { PublicCase } from '../entities/cases/PublicCase';
import {
Expand Down Expand Up @@ -49,6 +53,10 @@ const getSealedCase = ({
}
}

if (!User.isInternalUser(authorizedUser.role)) {
filterDocketEntriesNotOnDocketRecord({ authorizedUser, caseRecord });
}

if (isAuthorizedToViewSealedCase || isAssociatedWithCase) {
return new Case(caseRecord, { authorizedUser }).validate().toRawObject();
} else {
Expand All @@ -68,6 +76,7 @@ const getCaseForExternalUser = ({
isAssociatedWithCase,
isAuthorizedToGetCase,
}) => {
filterDocketEntriesNotOnDocketRecord({ authorizedUser, caseRecord });
if (isAuthorizedToGetCase && isAssociatedWithCase) {
return new Case(caseRecord, { authorizedUser }).validate().toRawObject();
} else {
Expand Down Expand Up @@ -202,3 +211,18 @@ export const getCaseInteractor = async (
);
return caseDetailRaw;
};

const filterDocketEntriesNotOnDocketRecord = ({
authorizedUser,
caseRecord,
}: {
caseRecord: RawCase;
authorizedUser: AuthUser;
}) => {
caseRecord.docketEntries = caseRecord.docketEntries.filter(
d =>
d.isOnDocketRecord ||
(d.documentType === INITIAL_DOCUMENT_TYPES.stin.documentType &&
authorizedUser.role === ROLES.irsSuperuser),
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
SpecialTrialSession,
TrialSessionWorkingCopyNotes,
} from '@shared/business/entities/trialSessions/SpecialTrialSessions';
import { post } from '../requests';

export const getBulkSpecialTrialSessionCopyNotesInteractor = (
applicationContext,
{
specialTrialSessions,
}: {
specialTrialSessions: Array<SpecialTrialSession>;
},
): Array<TrialSessionWorkingCopyNotes> =>
post({
applicationContext,
body: { specialTrialSessions },
endpoint: '/trial-sessions/bulk-copy-notes',
});
5 changes: 5 additions & 0 deletions web-api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import { generateTrialCalendarPdfLambda } from './lambdas/trialSessions/generate
import { getAllFeatureFlagsLambda } from './lambdas/featureFlag/getAllFeatureFlagsLambda';
import { getAllUsersByRoleLambda } from '@web-api/lambdas/users/getAllUsersByRoleLambda';
import { getBlockedCasesLambda } from './lambdas/reports/getBlockedCasesLambda';
import { getBulkTrialSessionCopyNotesLambda } from './lambdas/trialSessions/getBulkTrialSessionCopyNotesLambda';
import { getCalendaredCasesForTrialSessionLambda } from './lambdas/trialSessions/getCalendaredCasesForTrialSessionLambda';
import { getCaseDeadlinesForCaseLambda } from './lambdas/caseDeadline/getCaseDeadlinesForCaseLambda';
import { getCaseDeadlinesLambda } from './lambdas/caseDeadline/getCaseDeadlinesLambda';
Expand Down Expand Up @@ -921,6 +922,10 @@ app.delete(
'/trial-sessions/:trialSessionId/working-copy',
lambdaWrapper(getTrialSessionWorkingCopyLambda),
);
app.post(
'/trial-sessions/bulk-copy-notes',
lambdaWrapper(getBulkTrialSessionCopyNotesLambda),
);
app.put(
'/trial-sessions/:trialSessionId/working-copy',
lambdaWrapper(updateTrialSessionWorkingCopyLambda),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { UnauthorizedError } from '@web-api/errors/errors';
import { applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext';
import { getBulkTrialSessionCopyNotesInteractor } from './getBulkTrialSessionCopyNotesInteractor';
import { mockAdminUser, mockJudgeUser } from '@shared/test/mockAuthUsers';

const MOCK_WORKING_COPY_NOTES = [
{
sessionNotes: 'Test notes',
trialSessionId: '123',
},
{
sessionNotes: 'Test notes 2',
trialSessionId: '456',
},
];
describe('getBulkTrialSessionCopyNotesInteractor', () => {
beforeEach(() => {
applicationContext
.getPersistenceGateway()
.getBulkTrialSessionWorkingCopyNotes.mockReturnValue(
MOCK_WORKING_COPY_NOTES,
);
});
it('should throw an error if the user is unauthorized', async () => {
await expect(
getBulkTrialSessionCopyNotesInteractor(
applicationContext,
{ specialTrialSessions: [] },
mockAdminUser,
),
).rejects.toThrow(UnauthorizedError);
});

it('should return session notes for multiple trial sessions', async () => {
const result = await getBulkTrialSessionCopyNotesInteractor(
applicationContext,
{
specialTrialSessions: [
{ trialSessionId: '123', userId: '123' },
{ trialSessionId: '456', userId: '456' },
],
},
mockJudgeUser,
);
expect(result).toEqual(MOCK_WORKING_COPY_NOTES);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {
ROLE_PERMISSIONS,
isAuthorized,
} from '../../../../../shared/src/authorization/authorizationClientService';
import { ServerApplicationContext } from '@web-api/applicationContext';
import {
SpecialTrialSession,
SpecialTrialSessionKey,
TrialSessionWorkingCopyNotes,
} from '@shared/business/entities/trialSessions/SpecialTrialSessions';
import { UnauthorizedError } from '@web-api/errors/errors';
import { UnknownAuthUser } from '@shared/business/entities/authUser/AuthUser';

export const getBulkTrialSessionCopyNotesInteractor = async (
applicationContext: ServerApplicationContext,
{ specialTrialSessions }: { specialTrialSessions: SpecialTrialSession[] },
authorizedUser: UnknownAuthUser,
): Promise<Array<TrialSessionWorkingCopyNotes>> => {
if (!isAuthorized(authorizedUser, ROLE_PERMISSIONS.TRIAL_SESSIONS)) {
throw new UnauthorizedError('Unauthorized');
}

const specialTrialSessionKeys: Array<SpecialTrialSessionKey> =
specialTrialSessions.map(
(t: SpecialTrialSession): SpecialTrialSessionKey => ({
pk: `trial-session-working-copy|${t.trialSessionId}`,
sk: `user|${t.userId}`,
}),
);

return await applicationContext
.getPersistenceGateway()
.getBulkTrialSessionWorkingCopyNotes({
applicationContext,
specialTrialSessions: specialTrialSessionKeys,
});
};
2 changes: 2 additions & 0 deletions web-api/src/getPersistenceGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { getAllPendingMotionDocketEntriesForJudge } from '@web-api/persistence/e
import { getAllUsersByRole } from '@web-api/persistence/elasticsearch/users/getAllUsersByRole';
import { getAllWebSocketConnections } from './persistence/dynamo/notifications/getAllWebSocketConnections';
import { getBlockedCases } from './persistence/elasticsearch/getBlockedCases';
import { getBulkTrialSessionWorkingCopies } from './persistence/dynamo/trialSessions/getBulkTrialSessionWorkingCopies';
import { getCalendaredCasesForTrialSession } from './persistence/dynamo/trialSessions/getCalendaredCasesForTrialSession';
import { getCaseByDocketNumber } from './persistence/dynamo/cases/getCaseByDocketNumber';
import { getCaseDeadlinesByDateRange } from './persistence/elasticsearch/caseDeadlines/getCaseDeadlinesByDateRange';
Expand Down Expand Up @@ -286,6 +287,7 @@ const gatewayMethods = {
getAllUsersByRole,
getAllWebSocketConnections,
getBlockedCases,
getBulkTrialSessionWorkingCopyNotes: getBulkTrialSessionWorkingCopies,
getCalendaredCasesForTrialSession,
getCaseByDocketNumber,
getCaseDeadlinesByDateRange,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { UnknownAuthUser } from '@shared/business/entities/authUser/AuthUser';
import { genericHandler } from '../../genericHandler';
import { getBulkTrialSessionCopyNotesInteractor } from '@web-api/business/useCases/trialSessions/getBulkTrialSessionCopyNotesInteractor';

export const getBulkTrialSessionCopyNotesLambda = (
event,
authorizedUser: UnknownAuthUser,
) =>
genericHandler(event, async ({ applicationContext }) => {
const { specialTrialSessions } = JSON.parse(event.body || '{}');
return await getBulkTrialSessionCopyNotesInteractor(
applicationContext,
{
specialTrialSessions,
},
authorizedUser,
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext';
import { batchGet } from '../../dynamodbClientService';
import { getBulkTrialSessionWorkingCopies } from './getBulkTrialSessionWorkingCopies';

jest.mock('../../dynamodbClientService');

const batchGetMock = batchGet as jest.Mock;

batchGetMock.mockReturnValue([
{
caseMetadata: {},
entityName: 'TrialSessionWorkingCopy',
filters: {
basisReached: true,
continued: true,
definiteTrial: true,
dismissed: true,
motionToDismiss: true,
probableSettlement: true,
probableTrial: true,
recall: true,
rule122: true,
setForTrial: true,
settled: true,
showAll: true,
statusUnassigned: true,
submittedCAV: true,
},
pk: 'trial-session-working-copy|111ac21b-99f9-4321-98c8-b95db00af96b',
sessionNotes: 'Judge Colvin Super notes!',
sk: 'user|dabbad00-18d0-43ec-bafb-654e83405416',
sort: 'docket',
sortOrder: 'asc',
trialSessionId: '111ac21b-99f9-4321-98c8-b95db00af96b',
userId: 'dabbad00-18d0-43ec-bafb-654e83405416',
},
{
caseMetadata: {},
entityName: 'TrialSessionWorkingCopy',
filters: {
basisReached: true,
continued: true,
definiteTrial: true,
dismissed: true,
motionToDismiss: true,
probableSettlement: true,
probableTrial: true,
recall: true,
rule122: true,
setForTrial: true,
settled: true,
showAll: true,
statusUnassigned: true,
submittedCAV: true,
},
pk: 'trial-session-working-copy|0d943468-bc2e-4631-84e3-b084cf5b1fbb',
sessionNotes: 'Cohen Cohen Cohen Notes',
sk: 'user|dabbad04-18d0-43ec-bafb-654e83405416',
sort: 'docket',
sortOrder: 'asc',
trialSessionId: '0d943468-bc2e-4631-84e3-b084cf5b1fbb',
userId: 'dabbad04-18d0-43ec-bafb-654e83405416',
},
]);

describe('getBulkTrialSessionWorkingCopies', () => {
it('should get the trial session notes by special session array', async () => {
const specialTrialSessions = [
{ pk: '123', sk: '456' },
{ pk: '456', sk: '789' },
];

const result = await getBulkTrialSessionWorkingCopies({
applicationContext,
specialTrialSessions,
});
expect(result).toEqual([
{
sessionNotes: 'Judge Colvin Super notes!',
trialSessionId: '111ac21b-99f9-4321-98c8-b95db00af96b',
},
{
sessionNotes: 'Cohen Cohen Cohen Notes',
trialSessionId: '0d943468-bc2e-4631-84e3-b084cf5b1fbb',
},
]);
expect(batchGetMock).toHaveBeenCalledWith({
applicationContext,
keys: specialTrialSessions,
});
});
});
Loading

0 comments on commit f52f423

Please sign in to comment.