Skip to content

Commit

Permalink
Use new endpoints to get request types and to create new request
Browse files Browse the repository at this point in the history
  • Loading branch information
artem-blazhko committed Sep 16, 2024
1 parent 4dd62be commit b44b831
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Add missing sub-permissions to fetch staff slips records. Refs UIREQ-1129.
* Add missing sub-permissions to fetch "pick-slips" and "search-slips" records in "Requests: View, edit, cancel" permission. Refs UIREQ-1137.
* Update permissions set to be able to get item/instance information. Refs UIREQ-1148.
* *BREAKING* Migrate to new endpoints to get request types and to create a new request. Refs UIREQ-1113.

## [9.1.1] (https://github.com/folio-org/ui-checkin/tree/v9.1.1) (2024-03-27)
[Full Changelog](https://github.com/folio-org/ui-checkin/compare/v9.1.0...v9.1.1)
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@
"circulation.search-slips.get",
"circulation.print-events-entry.item.post",
"inventory-storage.locations.item.get",
"circulation.items-by-instance.get"
"circulation.items-by-instance.get",
"tlr.ecs-tlr-allowed-service-points.get",
"tlr.ecs-tlr.post"
],
"visible": true
},
Expand Down
15 changes: 15 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,18 @@ export const SETTINGS_SCOPES = {
export const SETTINGS_KEYS = {
GENERAL_TLR: 'generalTlr',
};

export const REQUEST_ACTION_NAMES = {
CREATE_REQUEST: 'CREATE_REQUEST',
GET_SERVICE_POINTS: 'GET_SERVICE_POINTS',
};

export const SINGLE_TENANT_URLS = {
[REQUEST_ACTION_NAMES.CREATE_REQUEST]: 'circulation/requests',
[REQUEST_ACTION_NAMES.GET_SERVICE_POINTS]: 'circulation/requests/allowed-service-points',
};

export const CENTRAL_TENANT_URLS = {
[REQUEST_ACTION_NAMES.CREATE_REQUEST]: 'tlr/ecs-tlr',
[REQUEST_ACTION_NAMES.GET_SERVICE_POINTS]: 'tlr/allowed-service-points',
};
58 changes: 48 additions & 10 deletions src/routes/RequestsRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
isEmpty,
isArray,
size,
unset,
cloneDeep,
} from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
Expand Down Expand Up @@ -68,6 +70,8 @@ import {
SETTINGS_SCOPES,
SETTINGS_KEYS,
ITEM_QUERIES,
REQUEST_ACTION_NAMES,
CENTRAL_TENANT_URLS,
PRINT_DETAILS_COLUMNS,
RESOURCE_TYPES,
requestFilterTypes,
Expand All @@ -85,6 +89,7 @@ import {
getSelectedSlipDataMulti,
selectedRowsNonPrintable,
getNextSelectedRowsState,
getRequestUrl,
isMultiDataTenant,
} from '../utils';
import packageInfo from '../../package';
Expand Down Expand Up @@ -146,6 +151,7 @@ export const getLastPrintedDetails = (printDetails, intl) => {
export const urls = {
user: (value, idType) => {
const query = stringify({ query: `(${idType}=="${value}")` });

return `users?${query}`;
},
item: (value, idType) => {
Expand Down Expand Up @@ -208,12 +214,14 @@ export const urls = {
instanceId,
requestId,
operation,
}) => {
}, idType, stripes) => {
const url = getRequestUrl(REQUEST_ACTION_NAMES.GET_SERVICE_POINTS, stripes);

if (requestId) {
return `circulation/requests/allowed-service-points?operation=${operation}&requestId=${requestId}`;
return `${url}?operation=${operation}&requestId=${requestId}`;
}

let requestUrl = `circulation/requests/allowed-service-points?requesterId=${requesterId}&operation=${operation}`;
let requestUrl = `${url}?requesterId=${requesterId}&operation=${operation}`;

if (itemId) {
requestUrl = `${requestUrl}&itemId=${itemId}`;
Expand Down Expand Up @@ -365,6 +373,12 @@ class RequestsRoute extends React.Component {
staticFallback: { params: {} },
},
},
ecsTlrRecords: {
type: 'okapi',
path: CENTRAL_TENANT_URLS[REQUEST_ACTION_NAMES.CREATE_REQUEST],
fetch: false,
throwErrors: false,
},
reportRecords: {
type: 'okapi',
path: 'circulation/requests',
Expand Down Expand Up @@ -504,6 +518,9 @@ class RequestsRoute extends React.Component {
GET: PropTypes.func,
POST: PropTypes.func,
}),
ecsTlrRecords: PropTypes.shape({
POST: PropTypes.func,
}),
reportRecords: PropTypes.shape({
GET: PropTypes.func,
}),
Expand Down Expand Up @@ -1000,7 +1017,9 @@ class RequestsRoute extends React.Component {
const { stripes } = this.props;
const query = urls[resource](value, idType, stripes);

return fetch(`${this.okapiUrl}/${query}`, this.httpHeadersOptions).then(response => response.json());
return fetch(`${this.okapiUrl}/${query}`, this.httpHeadersOptions)
.then(response => response.json())
.catch(() => null);
}

toggleModal() {
Expand Down Expand Up @@ -1097,26 +1116,45 @@ class RequestsRoute extends React.Component {
this.props.mutator.activeRecord.update({ patronId: patron.id });
};

create = (data) => {
create = (requestData) => {
const { stripes } = this.props;
const userPersonalData = cloneDeep(requestData?.requester?.personal);
let mutator = this.props.mutator.records;

if (isMultiDataTenant(stripes) && checkIfUserInCentralTenant(stripes)) {
unset(requestData, 'item');
unset(requestData, 'requester');
unset(requestData, 'holdingsRecordId');

mutator = this.props.mutator.ecsTlrRecords;
}

const query = new URLSearchParams(this.props.location.search);
const mode = query.get('mode');

return this.props.mutator.records.POST(data)
.then(() => {
this.closeLayer();
return mutator.POST(requestData)
.then((res) => {
const {
match: {
path,
},
history,
} = this.props;

history.push(`${path}/view/${res?.primaryRequestId || res?.id}`);

this.context.sendCallout({
message: isDuplicateMode(mode)
? (
<FormattedMessage
id="ui-requests.duplicateRequest.success"
values={{ requester: generateUserName(data.requester.personal) }}
values={{ requester: generateUserName(userPersonalData) }}
/>
)
: (
<FormattedMessage
id="ui-requests.createRequest.success"
values={{ requester: generateUserName(data.requester.personal) }}
values={{ requester: generateUserName(userPersonalData) }}
/>
),
});
Expand Down
97 changes: 90 additions & 7 deletions src/routes/RequestsRoute.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const testIds = {
rowCheckbox: 'rowCheckbox',
selectRequestCheckbox: 'selectRequestCheckbox',
};
const requestUrl = 'url';

const intlCache = createIntlCache();
const intl = createIntl(
Expand Down Expand Up @@ -115,6 +116,8 @@ jest.mock('../utils', () => ({
getNextSelectedRowsState: jest.fn(),
extractPickSlipRequestIds: jest.fn(),
isMultiDataTenant: jest.fn(),
generateUserName: jest.fn(),
getRequestUrl: jest.fn(() => requestUrl),
}));
jest.mock('./utils', () => ({
...jest.requireActual('./utils'),
Expand Down Expand Up @@ -238,6 +241,12 @@ const mockedRequest = {
},
id: 'requestId',
};
const userData = {
requester: {
personal: {},
}
};
const createRequestButtonLabel = 'Create request';
const printDetailsMockData = {
count: 11,
lastPrintedDate: '2024-08-03T13:33:31.868Z',
Expand All @@ -264,6 +273,7 @@ SearchAndSort.mockImplementation(jest.fn(({
customPaneSub,
columnMapping,
resultsFormatter,
onCreate,
}) => {
const onClickActions = () => {
onDuplicate(parentResources.records.records[0]);
Expand Down Expand Up @@ -315,6 +325,12 @@ SearchAndSort.mockImplementation(jest.fn(({
})}
>onFilterChange
</button>
<button
type="button"
onClick={() => onCreate(userData)}
>
{createRequestButtonLabel}
</button>
</div>
{actionMenu({ onToggle: jest.fn() })}
<div paneTitleRef={paneTitleRef} />
Expand Down Expand Up @@ -715,11 +731,70 @@ describe('RequestsRoute', () => {
});
});

describe('When single data tenant', () => {
const response = {
id: 'responseId',
};
const props = {
...defaultProps,
mutator: {
...defaultProps.mutator,
records: {
...defaultProps.mutator.records,
POST: jest.fn().mockResolvedValue(response),
},
},
};

beforeEach(() => {
isMultiDataTenant.mockReturnValue(false);
renderComponent(props);
});

it('should handle request creation', () => {
const createRequestButton = screen.getByText(createRequestButtonLabel);

fireEvent.click(createRequestButton);

expect(props.mutator.records.POST).toHaveBeenCalledWith(userData);
});

it('should redirect to details page', async () => {
const createRequestButton = screen.getByText(createRequestButtonLabel);

fireEvent.click(createRequestButton);

await waitFor(() => {
expect(props.history.push).toHaveBeenCalledWith(`${props.match.path}/view/${response.id}`);
});
});

it('should send callout', async () => {
const createRequestButton = screen.getByText(createRequestButtonLabel);

sendCallout.mockClear();
fireEvent.click(createRequestButton);

await waitFor(() => {
expect(sendCallout).toHaveBeenCalled();
});
});
});

describe('When multi data tenant', () => {
const requestHeaders = { test: 'test' };
const fetchSpy = jest.fn();
const response = {
id: 'responseId',
};
const props = {
...defaultProps,
mutator: {
...defaultProps.mutator,
ecsTlrRecords: {
POST: jest.fn().mockResolvedValue(response),
},
},
stripes: {
...defaultProps.stripes,
user: {
Expand Down Expand Up @@ -747,14 +822,22 @@ describe('RequestsRoute', () => {
ecsTlrFeatureEnabled: true,
}),
});
checkIfUserInCentralTenant.mockReturnValueOnce(true);
checkIfUserInCentralTenant.mockReturnValue(true);
global.fetch = fetchSpy;
renderComponent(props);
});

it('should use correct endpoint to get ecs tlr settings', () => {
expect(fetchSpy).toHaveBeenCalledWith(`${defaultProps.stripes.okapi.url}/tlr/settings`, requestHeaders);
});

it('should handle request creation', () => {
const createRequestButton = screen.getByText(createRequestButtonLabel);

fireEvent.click(createRequestButton);

expect(props.mutator.ecsTlrRecords.POST).toHaveBeenCalledWith(userData);
});
});

describe('When user in data tenant', () => {
Expand Down Expand Up @@ -1747,33 +1830,33 @@ describe('RequestsRoute', () => {
const instanceId = 'instanceIdUrl';

it('should return url with "itemId"', () => {
const expectedUrl = `circulation/requests/allowed-service-points?requesterId=${requesterId}&operation=${operation}&itemId=${itemId}`;
const expectedResult = `${requestUrl}?requesterId=${requesterId}&operation=${operation}&itemId=${itemId}`;

expect(urls.requestTypes({
requesterId,
itemId,
operation,
})).toBe(expectedUrl);
})).toBe(expectedResult);
});

it('should return url with "instanceId"', () => {
const expectedUrl = `circulation/requests/allowed-service-points?requesterId=${requesterId}&operation=${operation}&instanceId=${instanceId}`;
const expectedResult = `${requestUrl}?requesterId=${requesterId}&operation=${operation}&instanceId=${instanceId}`;

expect(urls.requestTypes({
requesterId,
instanceId,
operation,
})).toBe(expectedUrl);
})).toBe(expectedResult);
});

it('should return url with "requestId"', () => {
const requestId = 'requestId';
const expectedUrl = `circulation/requests/allowed-service-points?operation=${operation}&requestId=${requestId}`;
const expectedResult = `${requestUrl}?operation=${operation}&requestId=${requestId}`;

expect(urls.requestTypes({
requestId,
operation,
})).toBe(expectedUrl);
})).toBe(expectedResult);
});
});

Expand Down
Loading

0 comments on commit b44b831

Please sign in to comment.