Skip to content

Commit 43d97ee

Browse files
authored
Merge pull request #5269 from msupply-foundation/5242-add-delete-response-requisitions
5242 add delete response requisitions
2 parents 99da54e + db379c0 commit 43d97ee

File tree

20 files changed

+1027
-10
lines changed

20 files changed

+1027
-10
lines changed

client/packages/common/src/intl/locales/en/common.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,10 @@
14721472
"messages.zero-line-quantities_one": "The quantity of 1 line has been set to 0",
14731473
"messages.zero-line-quantities_other": "The quantity of {{count}} lines has been set to 0",
14741474
"messages.zero-return-quantity-will-delete-lines": "There are no return quantities specified. Click OK again to confirm and remove these lines from the return.",
1475+
"messages.cannot-delete-finalised-requisition": "Cannot delete finalised requisition",
1476+
"messages.record-not-found": "Record not found",
1477+
"messages.cannot-delete-requisition-with-shipment": "Cannot delete requisition linked to a shipment",
1478+
"messages.cannot-delete-transfer-requisition": "Cannot delete transfer requisition",
14751479
"monitoring": "Monitoring",
14761480
"multiple": "[multiple]",
14771481
"outbound-shipment": "Outbound Shipments",

client/packages/common/src/types/schema.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,11 +767,13 @@ export type BatchRequestRequisitionResponse = {
767767
export type BatchResponseRequisitionInput = {
768768
continueOnError?: InputMaybe<Scalars['Boolean']['input']>;
769769
deleteResponseRequisitionLines?: InputMaybe<Array<DeleteResponseRequisitionLineInput>>;
770+
deleteResponseRequisitions?: InputMaybe<Array<DeleteResponseRequisitionInput>>;
770771
};
771772

772773
export type BatchResponseRequisitionResponse = {
773774
__typename: 'BatchResponseRequisitionResponse';
774775
deleteResponseRequisitionLines?: Maybe<Array<DeleteResponseRequisitionLineResponseWithId>>;
776+
deleteResponseRequisitions?: Maybe<Array<DeleteResponseRequisitionResponseWithId>>;
775777
};
776778

777779
export type BatchStocktakeInput = {
@@ -1588,6 +1590,19 @@ export type DeleteResponse = {
15881590
id: Scalars['String']['output'];
15891591
};
15901592

1593+
export type DeleteResponseRequisitionError = {
1594+
__typename: 'DeleteResponseRequisitionError';
1595+
error: DeleteResponseRequisitionErrorInterface;
1596+
};
1597+
1598+
export type DeleteResponseRequisitionErrorInterface = {
1599+
description: Scalars['String']['output'];
1600+
};
1601+
1602+
export type DeleteResponseRequisitionInput = {
1603+
id: Scalars['String']['input'];
1604+
};
1605+
15911606
export type DeleteResponseRequisitionLineError = {
15921607
__typename: 'DeleteResponseRequisitionLineError';
15931608
error: DeleteResponseRequisitionLineErrorInterface;
@@ -1609,6 +1624,14 @@ export type DeleteResponseRequisitionLineResponseWithId = {
16091624
response: DeleteResponseRequisitionLineResponse;
16101625
};
16111626

1627+
export type DeleteResponseRequisitionResponse = DeleteResponse | DeleteResponseRequisitionError;
1628+
1629+
export type DeleteResponseRequisitionResponseWithId = {
1630+
__typename: 'DeleteResponseRequisitionResponseWithId';
1631+
id: Scalars['String']['output'];
1632+
response: DeleteResponseRequisitionResponse;
1633+
};
1634+
16121635
export type DeleteStocktakeError = {
16131636
__typename: 'DeleteStocktakeError';
16141637
error: DeleteStocktakeErrorInterface;
@@ -2209,6 +2232,11 @@ export type FinaliseRnRFormInput = {
22092232

22102233
export type FinaliseRnRFormResponse = RnRFormNode;
22112234

2235+
export type FinalisedRequisition = DeleteResponseRequisitionErrorInterface & {
2236+
__typename: 'FinalisedRequisition';
2237+
description: Scalars['String']['output'];
2238+
};
2239+
22122240
export enum ForeignKey {
22132241
InvoiceId = 'invoiceId',
22142242
ItemId = 'itemId',
@@ -3704,6 +3732,11 @@ export type LedgerSortInput = {
37043732
key: LedgerSortFieldInput;
37053733
};
37063734

3735+
export type LineDeleteError = DeleteResponseRequisitionErrorInterface & {
3736+
__typename: 'LineDeleteError';
3737+
description: Scalars['String']['output'];
3738+
};
3739+
37073740
export type LinkPatientPatientToStoreError = {
37083741
__typename: 'LinkPatientPatientToStoreError';
37093742
error: LinkPatientPatientToStoreErrorInterface;
@@ -3948,6 +3981,7 @@ export type Mutations = {
39483981
deletePrescriptionLine: DeletePrescriptionLineResponse;
39493982
deleteRequestRequisition: DeleteRequestRequisitionResponse;
39503983
deleteRequestRequisitionLine: DeleteRequestRequisitionLineResponse;
3984+
deleteResponseRequisition: DeleteResponseRequisitionResponse;
39513985
deleteResponseRequisitionLine: DeleteResponseRequisitionLineResponse;
39523986
deleteStocktake: DeleteStocktakeResponse;
39533987
deleteStocktakeLine: DeleteStocktakeLineResponse;
@@ -4216,6 +4250,12 @@ export type MutationsDeleteRequestRequisitionLineArgs = {
42164250
};
42174251

42184252

4253+
export type MutationsDeleteResponseRequisitionArgs = {
4254+
input: DeleteResponseRequisitionInput;
4255+
storeId: Scalars['String']['input'];
4256+
};
4257+
4258+
42194259
export type MutationsDeleteResponseRequisitionLineArgs = {
42204260
input: DeleteResponseRequisitionLineInput;
42214261
storeId: Scalars['String']['input'];
@@ -6286,7 +6326,7 @@ export type RecordBelongsToAnotherStore = DeleteAssetErrorInterface & DeleteAsse
62866326
description: Scalars['String']['output'];
62876327
};
62886328

6289-
export type RecordNotFound = AddFromMasterListErrorInterface & AddToInboundShipmentFromMasterListErrorInterface & AddToOutboundShipmentFromMasterListErrorInterface & AllocateOutboundShipmentUnallocatedLineErrorInterface & CreateRequisitionShipmentErrorInterface & DeleteAssetCatalogueItemErrorInterface & DeleteAssetErrorInterface & DeleteAssetLogReasonErrorInterface & DeleteCustomerReturnErrorInterface & DeleteErrorInterface & DeleteInboundShipmentErrorInterface & DeleteInboundShipmentLineErrorInterface & DeleteInboundShipmentServiceLineErrorInterface & DeleteLocationErrorInterface & DeleteOutboundShipmentLineErrorInterface & DeleteOutboundShipmentServiceLineErrorInterface & DeleteOutboundShipmentUnallocatedLineErrorInterface & DeletePrescriptionErrorInterface & DeletePrescriptionLineErrorInterface & DeleteRequestRequisitionErrorInterface & DeleteRequestRequisitionLineErrorInterface & DeleteResponseRequisitionLineErrorInterface & DeleteSupplierReturnErrorInterface & DeleteVaccineCourseErrorInterface & NodeErrorInterface & RequisitionLineChartErrorInterface & RequisitionLineStatsErrorInterface & SupplyRequestedQuantityErrorInterface & UpdateAssetErrorInterface & UpdateErrorInterface & UpdateInboundShipmentErrorInterface & UpdateInboundShipmentLineErrorInterface & UpdateInboundShipmentServiceLineErrorInterface & UpdateLocationErrorInterface & UpdateNameErrorInterface & UpdateNamePropertiesErrorInterface & UpdateOutboundShipmentLineErrorInterface & UpdateOutboundShipmentServiceLineErrorInterface & UpdateOutboundShipmentUnallocatedLineErrorInterface & UpdatePrescriptionErrorInterface & UpdatePrescriptionLineErrorInterface & UpdateRequestRequisitionErrorInterface & UpdateRequestRequisitionLineErrorInterface & UpdateResponseRequisitionErrorInterface & UpdateResponseRequisitionLineErrorInterface & UpdateReturnOtherPartyErrorInterface & UpdateSensorErrorInterface & UpdateStockLineErrorInterface & UseSuggestedQuantityErrorInterface & {
6329+
export type RecordNotFound = AddFromMasterListErrorInterface & AddToInboundShipmentFromMasterListErrorInterface & AddToOutboundShipmentFromMasterListErrorInterface & AllocateOutboundShipmentUnallocatedLineErrorInterface & CreateRequisitionShipmentErrorInterface & DeleteAssetCatalogueItemErrorInterface & DeleteAssetErrorInterface & DeleteAssetLogReasonErrorInterface & DeleteCustomerReturnErrorInterface & DeleteErrorInterface & DeleteInboundShipmentErrorInterface & DeleteInboundShipmentLineErrorInterface & DeleteInboundShipmentServiceLineErrorInterface & DeleteLocationErrorInterface & DeleteOutboundShipmentLineErrorInterface & DeleteOutboundShipmentServiceLineErrorInterface & DeleteOutboundShipmentUnallocatedLineErrorInterface & DeletePrescriptionErrorInterface & DeletePrescriptionLineErrorInterface & DeleteRequestRequisitionErrorInterface & DeleteRequestRequisitionLineErrorInterface & DeleteResponseRequisitionErrorInterface & DeleteResponseRequisitionLineErrorInterface & DeleteSupplierReturnErrorInterface & DeleteVaccineCourseErrorInterface & NodeErrorInterface & RequisitionLineChartErrorInterface & RequisitionLineStatsErrorInterface & SupplyRequestedQuantityErrorInterface & UpdateAssetErrorInterface & UpdateErrorInterface & UpdateInboundShipmentErrorInterface & UpdateInboundShipmentLineErrorInterface & UpdateInboundShipmentServiceLineErrorInterface & UpdateLocationErrorInterface & UpdateNameErrorInterface & UpdateNamePropertiesErrorInterface & UpdateOutboundShipmentLineErrorInterface & UpdateOutboundShipmentServiceLineErrorInterface & UpdateOutboundShipmentUnallocatedLineErrorInterface & UpdatePrescriptionErrorInterface & UpdatePrescriptionLineErrorInterface & UpdateRequestRequisitionErrorInterface & UpdateRequestRequisitionLineErrorInterface & UpdateResponseRequisitionErrorInterface & UpdateResponseRequisitionLineErrorInterface & UpdateReturnOtherPartyErrorInterface & UpdateSensorErrorInterface & UpdateStockLineErrorInterface & UseSuggestedQuantityErrorInterface & {
62906330
__typename: 'RecordNotFound';
62916331
description: Scalars['String']['output'];
62926332
};
@@ -6649,6 +6689,11 @@ export type RequisitionSortInput = {
66496689
key: RequisitionSortFieldInput;
66506690
};
66516691

6692+
export type RequisitionWithShipment = DeleteResponseRequisitionErrorInterface & {
6693+
__typename: 'RequisitionWithShipment';
6694+
description: Scalars['String']['output'];
6695+
};
6696+
66526697
export type RequisitionsResponse = RequisitionConnector;
66536698

66546699
export type ResponseRequisitionCounts = {
@@ -7498,6 +7543,11 @@ export type TokenExpired = RefreshTokenErrorInterface & {
74987543
description: Scalars['String']['output'];
74997544
};
75007545

7546+
export type TransferredRequisition = DeleteResponseRequisitionErrorInterface & {
7547+
__typename: 'TransferredRequisition';
7548+
description: Scalars['String']['output'];
7549+
};
7550+
75017551
export type UnallocatedLineForItemAlreadyExists = InsertOutboundShipmentUnallocatedLineErrorInterface & {
75027552
__typename: 'UnallocatedLineForItemAlreadyExists';
75037553
description: Scalars['String']['output'];

client/packages/requisitions/src/ResponseRequisition/ListView/ListView.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@ export const ResponseRequisitionListView: FC = () => {
131131
t(getApprovalStatusKey(rowData.approvalStatus)),
132132
});
133133
}
134-
columnDefinitions.push(['comment', { minWidth: 400, Cell: TooltipTextCell }]);
134+
columnDefinitions.push(
135+
['comment', { minWidth: 350, Cell: TooltipTextCell }],
136+
['selection']
137+
);
135138

136139
const columns = useColumns<ResponseRowFragment>(
137140
columnDefinitions,

client/packages/requisitions/src/ResponseRequisition/ListView/Toolbar.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ import {
66
Box,
77
useTranslation,
88
RequisitionNodeStatus,
9+
DeleteIcon,
10+
DropdownMenu,
11+
DropdownMenuItem,
912
} from '@openmsupply-client/common';
13+
import { useResponse } from '../api';
1014

1115
export const Toolbar: FC<{
1216
filter: FilterController;
1317
}> = () => {
18+
const onDelete = useResponse.document.deleteSelected();
1419
const t = useTranslation();
1520

1621
return (
@@ -51,6 +56,11 @@ export const Toolbar: FC<{
5156
]}
5257
/>
5358
</Box>
59+
<DropdownMenu label={t('label.actions')}>
60+
<DropdownMenuItem IconComponent={DeleteIcon} onClick={onDelete}>
61+
{t('button.delete-lines')}
62+
</DropdownMenuItem>
63+
</DropdownMenu>
5464
</AppBarContentPortal>
5565
);
5666
};

client/packages/requisitions/src/ResponseRequisition/api/api.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ const responseParser = {
8282
status: responseParser.toStatus(requisition),
8383
};
8484
},
85+
toDelete: (line: ResponseFragment) => {
86+
return { id: line.id };
87+
},
8588
toDeleteLine: (line: ResponseLineFragment) => ({ id: line.id }),
8689
toUpdateLine: (
8790
patch: DraftResponseLine
@@ -223,6 +226,23 @@ export const getResponseQueries = (sdk: Sdk, storeId: string) => ({
223226

224227
throw new Error('Unable to update requisition');
225228
},
229+
deleteResponses: async (requisitions: ResponseFragment[]) => {
230+
const deleteResponseRequisitions = requisitions.map(
231+
responseParser.toDelete
232+
);
233+
const result = await sdk.deleteRequest({
234+
storeId,
235+
input: { deleteResponseRequisitions },
236+
});
237+
238+
const { batchResponseRequisition } = result || {};
239+
240+
if (batchResponseRequisition?.deleteResponseRequisitions) {
241+
return batchResponseRequisition.deleteResponseRequisitions;
242+
}
243+
244+
throw new Error('Could not delete requisitions');
245+
},
226246
deleteLines: async (responseLines: ResponseLineFragment[]) => {
227247
const ids = responseLines.map(responseParser.toDeleteLine);
228248
const result = await sdk.deleteResponseLines({ ids, storeId });

client/packages/requisitions/src/ResponseRequisition/api/hooks/document/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ import { useResponseFields } from './useResponseFields';
55
import { useResponses } from './useResponses';
66
import { useResponsesAll } from './useResponsesAll';
77
import { useUpdateResponse } from './useUpdateResponse';
8+
import { useDeleteResponses } from './useDeleteResponses';
9+
import { useDeleteSelectedResponseRequisitions } from './useDeleteSelectedResponseRequisitions';
810

911
export const Document = {
1012
useResponse,
1113
useResponseFields,
1214
useResponses,
1315
useResponsesAll,
1416
useUpdateResponse,
17+
useDeleteResponses,
18+
useDeleteSelectedResponseRequisitions,
1519
useInsertResponse,
1620
useInsertProgramResponse,
1721
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useQueryClient, useMutation } from '@openmsupply-client/common';
2+
import { useResponseApi } from '../utils/useResponseApi';
3+
4+
export const useDeleteResponses = () => {
5+
const queryClient = useQueryClient();
6+
const api = useResponseApi();
7+
return useMutation(api.deleteResponses, {
8+
onSuccess: () => {
9+
queryClient.invalidateQueries(api.keys.base());
10+
},
11+
});
12+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
useTranslation,
3+
useTableStore,
4+
RequisitionNodeStatus,
5+
useDeleteConfirmation,
6+
useUrlQueryParams,
7+
} from '@openmsupply-client/common';
8+
import { ResponseFragment } from '../../operations.generated';
9+
import { useDeleteResponses } from './useDeleteResponses';
10+
import { useResponses } from './useResponses';
11+
12+
export const useDeleteSelectedResponseRequisitions = () => {
13+
const { queryParams } = useUrlQueryParams({
14+
initialSort: { key: 'createdDatetime', dir: 'desc' },
15+
});
16+
const { data: rows } = useResponses(queryParams);
17+
const { mutateAsync } = useDeleteResponses();
18+
const t = useTranslation();
19+
const { selectedRows } = useTableStore(state => ({
20+
selectedRows: Object.keys(state.rowState)
21+
.filter(id => state.rowState[id]?.isSelected)
22+
.map(selectedId => rows?.nodes?.find(({ id }) => selectedId === id))
23+
.filter(Boolean) as ResponseFragment[],
24+
}));
25+
const deleteAction = async () => {
26+
let result = await mutateAsync(selectedRows).catch(err => {
27+
throw err;
28+
});
29+
// check for errors
30+
result.forEach(line => {
31+
if (line.response.__typename == 'DeleteResponseRequisitionError') {
32+
switch (line.response.error.__typename) {
33+
case 'FinalisedRequisition':
34+
throw Error(t('messages.cannot-delete-finalised-requisition'));
35+
case 'RecordNotFound':
36+
throw Error(t('messages.record-not-found'));
37+
case 'RequisitionWithShipment':
38+
throw Error(t('messages.cannot-delete-requisition-with-shipment'));
39+
case 'TransferredRequisition':
40+
throw Error(t('messages.cannot-delete-transfer-requisition'));
41+
}
42+
}
43+
});
44+
};
45+
46+
const confirmAndDelete = useDeleteConfirmation({
47+
selectedRows,
48+
deleteAction,
49+
canDelete: selectedRows.every(
50+
({ status }) => status !== RequisitionNodeStatus.Finalised
51+
),
52+
messages: {
53+
confirmMessage: t('messages.confirm-delete-requisitions', {
54+
count: selectedRows.length,
55+
}),
56+
deleteSuccess: t('messages.deleted-orders', {
57+
count: selectedRows.length,
58+
}),
59+
cantDelete: (err: Error) => err.message,
60+
},
61+
});
62+
return confirmAndDelete;
63+
};

client/packages/requisitions/src/ResponseRequisition/api/hooks/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export const useResponse = {
1111
insert: Document.useInsertResponse,
1212
insertProgram: Document.useInsertProgramResponse,
1313
update: Document.useUpdateResponse,
14-
14+
delete: Document.useDeleteResponses,
15+
deleteSelected: Document.useDeleteSelectedResponseRequisitions,
1516
fields: Document.useResponseFields,
1617
},
1718
line: {

0 commit comments

Comments
 (0)