Skip to content

Commit

Permalink
UIOR-1325 UIOR-1351 Add submit actions for PO and PO Line forms (#1692)
Browse files Browse the repository at this point in the history
* UIOR-1325 UIOR-1351 Add submit actions for PO and PO Line forms

* fix broken tests

* update tests

* resolve lint issue
  • Loading branch information
usavkov-epam authored Jan 21, 2025
1 parent 6f6e869 commit 01dca38
Show file tree
Hide file tree
Showing 16 changed files with 995 additions and 666 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## 7.1.0 (IN PROGRESS)

* Display the “Record deleted” label in version history only if the UUID no longer exists. Refs UIOR-1355.
* Add the "Save & keep editing" button to the PO form. Refs UIOR-1325.
* Add the "Save & keep editing" button to the PO Line form. Refs UIOR-1351.

## [7.0.4](https://github.com/folio-org/ui-orders/tree/v7.0.4) (2024-12-31)
[Full Changelog](https://github.com/folio-org/ui-orders/compare/v7.0.3...v7.0.4)
Expand Down
2 changes: 2 additions & 0 deletions src/common/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,5 @@ export const CENTRAL_ORDERING_DEFAULT_RECEIVING_SEARCH = {
centralDefault: 'Central default',
activeAffiliationDefault: 'Active affiliation default',
};

export const SUBMIT_ACTION_FIELD = '__submitAction__';
7 changes: 6 additions & 1 deletion src/common/hooks/useOrder/useOrder.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export const useOrder = (orderId) => {
query: `id==${orderId}`,
};

const { isLoading, data } = useQuery(
const {
data,
isLoading,
refetch,
} = useQuery(
['ui-orders', 'order', orderId],
async () => {
try {
Expand All @@ -29,5 +33,6 @@ export const useOrder = (orderId) => {
return ({
order: data,
isLoading,
refetch,
});
};
32 changes: 22 additions & 10 deletions src/common/hooks/useOrderLine/useOrderLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ import {

import { LINES_API } from '@folio/stripes-acq-components';

export const useOrderLine = (lineId) => {
const ky = useOkapiKy();
const [namespace] = useNamespace({ key: 'order-versions' });
export const useOrderLine = (lineId, options = {}) => {
const {
enabled = true,
tenantId,
...queryOptions
} = options;

const { isLoading, data } = useQuery(
[namespace, lineId],
async () => ky.get(`${LINES_API}/${lineId}`).json(),
{
enabled: Boolean(lineId),
},
);
const [namespace] = useNamespace({ key: 'purchase-order-line' });
const ky = useOkapiKy({ tenant: tenantId });

const {
data,
isFetching,
isLoading,
refetch,
} = useQuery({
queryKey: [namespace, lineId, tenantId],
queryFn: ({ signal }) => ky.get(`${LINES_API}/${lineId}`, { signal }).json(),
enabled: enabled && Boolean(lineId),
...queryOptions,
});

return ({
orderLine: data,
isFetching,
isLoading,
refetch,
});
};
100 changes: 74 additions & 26 deletions src/components/LayerCollection/LayerPO.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import get from 'lodash/get';
import PropTypes from 'prop-types';
import { get } from 'lodash';
import {
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import { FormattedMessage } from 'react-intl';

import { LoadingView } from '@folio/stripes/components';
import {
stripesConnect,
} from '@folio/stripes/core';
import { stripesConnect } from '@folio/stripes/core';
import {
baseManifest,
ORDER_STATUSES,
Expand All @@ -16,9 +19,15 @@ import {
useShowCallout,
} from '@folio/stripes-acq-components';

import { SUBMIT_ACTION_FIELD } from '../../common/constants';
import {
createOrEditOrderResource,
} from '../Utils/orderResource';
useHandleOrderUpdateError,
useOrder,
} from '../../common/hooks';
import { SUBMIT_ACTION } from '../PurchaseOrder/constants';
import POForm from '../PurchaseOrder/POForm';
import { UpdateOrderErrorModal } from '../PurchaseOrder/UpdateOrderErrorModal';
import { createOrEditOrderResource } from '../Utils/orderResource';
import {
ADDRESSES,
ORDER,
Expand All @@ -27,9 +36,6 @@ import {
ORDER_TEMPLATES,
USERS,
} from '../Utils/resources';
import { useHandleOrderUpdateError } from '../../common/hooks/useHandleOrderUpdateError';
import POForm from '../PurchaseOrder/POForm';
import { UpdateOrderErrorModal } from '../PurchaseOrder/UpdateOrderErrorModal';

const NEW_ORDER = {
reEncumber: true,
Expand All @@ -53,8 +59,17 @@ function LayerPO({
const [isLoading, setIsLoading] = useState(true);
const [updateOrderError, setUpdateOrderError] = useState();
const [isErrorsModalOpened, toggleErrorsModal] = useModalToggle();
const order = id ? resources?.order?.records[0] : NEW_ORDER;

const instanceId = location.state?.instanceId;
const instanceTenantId = location.state?.instanceTenantId;

const {
order: fetchedOrder,
isLoading: isOrderLoading,
refetch,
} = useOrder(id);

const order = id ? fetchedOrder : NEW_ORDER;

useEffect(() => {
memoizedMutator.orderNumber.reset();
Expand All @@ -73,33 +88,56 @@ function LayerPO({
setUpdateOrderError(errors);
}, [toggleErrorsModal]);

const updatePO = useCallback(values => {
const updatePO = useCallback((values) => {
setIsLoading(true);
setSavingValues(values);

return createOrEditOrderResource(values, memoizedMutator.order)
.then(savedOrder => {
const { [SUBMIT_ACTION_FIELD]: submitAction, ...data } = values;

setSavingValues(data);

return createOrEditOrderResource(data, mutator.order)
.then((savedOrder) => {
sendCallout({
message: <FormattedMessage id="ui-orders.order.save.success" values={{ orderNumber: savedOrder.poNumber }} />,
});
history.push({
pathname: instanceId ? `/orders/view/${savedOrder.id}/po-line/create` : `/orders/view/${savedOrder.id}`,
search: location.search,
state: instanceId ? { instanceId, instanceTenantId: location.state?.instanceTenantId } : {},
});

return savedOrder;
})
.then(async (savedOrder) => {
setSavingValues(null);

switch (submitAction) {
case SUBMIT_ACTION.saveAndKeepEditing:
await refetch();

history.push({
pathname: `/orders/edit/${savedOrder.id}`,
search: location.search,
});
break;
case SUBMIT_ACTION.saveAndClose:
default:
history.push({
pathname: instanceId ? `/orders/view/${savedOrder.id}/po-line/create` : `/orders/view/${savedOrder.id}`,
search: location.search,
state: instanceId ? { instanceId, instanceTenantId } : {},
});
break;
}
})
.catch(async e => {
setIsLoading(false);
await handleErrorResponse(e, openOrderErrorModalShow);
});
})
.finally(() => setIsLoading(false));
}, [
handleErrorResponse,
history,
instanceId,
location.search,
location.state?.instanceTenantId,
memoizedMutator.order,
instanceTenantId,
mutator.order,
openOrderErrorModalShow,
refetch,
sendCallout,
]);

Expand All @@ -116,7 +154,14 @@ function LayerPO({
[history, id, location.search, instanceId],
);

if (isLoading || !order) return <LoadingView dismissible onClose={onCancel} />;
if (isLoading || isOrderLoading || !order) {
return (
<LoadingView
dismissible
onClose={onCancel}
/>
);
}

const { poNumber, poNumberPrefix, poNumberSuffix } = order;
const generatedNumber = get(resources, 'orderNumber.records.0.poNumber');
Expand Down Expand Up @@ -152,7 +197,10 @@ function LayerPO({
}

LayerPO.manifest = Object.freeze({
order: ORDER,
order: {
...ORDER,
fetch: false,
},
addresses: ADDRESSES,
users: {
...USERS,
Expand Down
48 changes: 38 additions & 10 deletions src/components/LayerCollection/LayerPO.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { MemoryRouter } from 'react-router';

import { render, screen, waitFor } from '@folio/jest-config-stripes/testing-library/react';
import {
render,
screen,
waitFor,
} from '@folio/jest-config-stripes/testing-library/react';
import { ORDER_TYPES } from '@folio/stripes-acq-components';

import {
Expand All @@ -12,23 +16,26 @@ import {
history,
location,
} from 'fixtures/routerMocks';
import { SUBMIT_ACTION_FIELD } from '../../common/constants';
import { useOrder } from '../../common/hooks';
import { SUBMIT_ACTION } from '../PurchaseOrder/constants';
import POForm from '../PurchaseOrder/POForm';
import LayerPO from './LayerPO';

jest.mock('../../common/hooks', () => ({
...jest.requireActual('../../common/hooks'),
useOrder: jest.fn(),
}));
jest.mock('../PurchaseOrder/POForm', () => jest.fn().mockReturnValue('POForm'));

const defaultProps = {
resourses: {
order: {
records: [order],
},
orderNumber: {
records: [{ poNumber: '10000' }],
},
},
mutator: {
order: {
GET: jest.fn().mockResolvedValue([order]),
POST: jest.fn().mockResolvedValue([order]),
PUT: jest.fn().mockResolvedValue([order]),
},
Expand Down Expand Up @@ -73,9 +80,14 @@ const renderLayerPO = (props = {}) => render(

describe('LayerPO', () => {
beforeEach(() => {
defaultProps.mutator.order.POST.mockClear();
history.push.mockClear();
POForm.mockClear();
useOrder.mockReturnValue({
order,
refetch: jest.fn(),
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('should render PO form', async () => {
Expand All @@ -101,7 +113,22 @@ describe('LayerPO', () => {
orderType: ORDER_TYPES.ongoing,
}));

expect(history.push).toHaveBeenCalled();
expect(history.push).toHaveBeenCalledWith(expect.objectContaining({
pathname: expect.stringMatching(/orders\/view/),
}));
});

it('should keep edit form opened if saveAndKeepEditing action was selected', async () => {
renderLayerPO();

await waitFor(() => POForm.mock.calls[0][0].onSubmit({
orderType: ORDER_TYPES.ongoing,
[SUBMIT_ACTION_FIELD]: SUBMIT_ACTION.saveAndKeepEditing,
}));

expect(history.push).toHaveBeenCalledWith(expect.objectContaining({
pathname: expect.stringMatching(/orders\/edit/),
}));
});

describe('Create from inventory', () => {
Expand All @@ -120,6 +147,7 @@ describe('LayerPO', () => {

await waitFor(() => POForm.mock.calls[0][0].onSubmit({
orderType: ORDER_TYPES.ongoing,
[SUBMIT_ACTION_FIELD]: SUBMIT_ACTION.saveAndClose,
}));

expect(history.push).toHaveBeenCalledWith(expect.objectContaining({
Expand All @@ -130,7 +158,7 @@ describe('LayerPO', () => {
});

it('should throw an error if the order update was failed ', async () => {
defaultProps.mutator.order.POST.mockRejectedValue({});
defaultProps.mutator.order.POST.mockRejectedValueOnce({});

renderLayerPO();

Expand Down
Loading

0 comments on commit 01dca38

Please sign in to comment.