@openmrs/esm-stock-management-app 1.0.1-pre.38 → 1.0.1-pre.380

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. package/dist/56.js +1 -0
  2. package/dist/56.js.map +1 -0
  3. package/dist/835.js +2 -0
  4. package/dist/835.js.map +1 -0
  5. package/dist/main.js +1 -1
  6. package/dist/main.js.map +1 -1
  7. package/dist/openmrs-esm-stock-management-app.js +1 -1
  8. package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +42 -42
  9. package/dist/openmrs-esm-stock-management-app.js.map +1 -1
  10. package/dist/routes.json +1 -1
  11. package/package.json +1 -1
  12. package/src/core/api/types/BatchJob.ts +2 -2
  13. package/src/stock-items/add-stock-item/stock-item-details/stock-item-details.component.tsx +0 -1
  14. package/src/stock-items/stock-items-table.component.tsx +22 -3
  15. package/src/stock-items/types.ts +79 -0
  16. package/src/stock-locations/add-locations-form.component.tsx +74 -0
  17. package/src/stock-locations/location-admin-form.component.tsx +164 -0
  18. package/src/stock-locations/stock-locations-table.component.tsx +33 -10
  19. package/src/stock-locations/stock-locations-table.resource.tsx +67 -12
  20. package/src/stock-locations/stock-locations-table.scss +3 -0
  21. package/src/stock-lookups/stock-lookups.resource.ts +1 -1
  22. package/src/stock-operations/add-stock-operation/add-stock-operation.component.tsx +18 -8
  23. package/src/stock-operations/add-stock-operation/add-stock-utils.ts +0 -2
  24. package/src/stock-operations/add-stock-operation/base-operation-details.component.tsx +28 -37
  25. package/src/stock-operations/stock-operation.utils.tsx +17 -2
  26. package/src/stock-operations/stock-operations-dialog/stock-operations-dialog.component.tsx +12 -12
  27. package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +10 -2
  28. package/src/stock-operations/stock-operations-table.component.tsx +16 -15
  29. package/src/stock-operations/validation-schema.ts +0 -3
  30. package/src/stock-reports/ReportType.ts +2 -2
  31. package/src/stock-reports/generate-report/create-stock-report.component.tsx +635 -31
  32. package/src/stock-reports/generate-report/create-stock-report.scss +9 -2
  33. package/src/stock-reports/report-list/stock-reports.component.tsx +8 -1
  34. package/src/stock-reports/report-validation-schema.ts +40 -0
  35. package/src/stock-user-role-scopes/add-stock-user-scope/add-stock-user-role-scope.component.tsx +7 -19
  36. package/tsconfig.json +2 -1
  37. package/dist/500.js +0 -2
  38. package/dist/500.js.map +0 -1
  39. package/dist/842.js +0 -1
  40. package/dist/842.js.map +0 -1
  41. /package/dist/{500.js.LICENSE.txt → 835.js.LICENSE.txt} +0 -0
@@ -0,0 +1,164 @@
1
+ import React, { useState } from "react";
2
+ import { z } from "zod";
3
+ import { useForm, Controller } from "react-hook-form";
4
+ import { zodResolver } from "@hookform/resolvers/zod";
5
+ import {
6
+ Button,
7
+ ComposedModal,
8
+ FormGroup,
9
+ ModalBody,
10
+ ModalFooter,
11
+ ModalHeader,
12
+ Stack,
13
+ TextInput,
14
+ InlineNotification,
15
+ FilterableMultiSelect,
16
+ InlineLoading,
17
+ } from "@carbon/react";
18
+ import { useTranslation } from "react-i18next";
19
+ import { locationData } from "../stock-items/types";
20
+ import styles from "./stock-locations-table.scss";
21
+ import { useLocationTags } from "./stock-locations-table.resource";
22
+
23
+ const LocationAdministrationSchema = z.object({
24
+ name: z.string().max(255),
25
+ });
26
+
27
+ interface LocationAdministrationFormProps {
28
+ showModal: boolean;
29
+ onModalChange: (showModal: boolean) => void;
30
+ handleCreateQuestion?: (formData: locationData) => void;
31
+ handleDeleteBedTag?: () => void;
32
+ headerTitle: string;
33
+ initialData: locationData;
34
+ }
35
+
36
+ interface ErrorType {
37
+ message: string;
38
+ }
39
+
40
+ const LocationAdministrationForm: React.FC<LocationAdministrationFormProps> = ({
41
+ showModal,
42
+ onModalChange,
43
+ handleCreateQuestion,
44
+ headerTitle,
45
+ initialData,
46
+ }) => {
47
+ const { t } = useTranslation();
48
+
49
+ const [showErrorNotification, setShowErrorNotification] = useState(false);
50
+ const [formStateError, setFormStateError] = useState("");
51
+
52
+ // Location tag types
53
+ const { locationTagList: Tags, loading: loadingRoles } = useLocationTags();
54
+
55
+ const {
56
+ handleSubmit,
57
+ control,
58
+ getValues,
59
+ formState: { isDirty },
60
+ } = useForm<locationData>({
61
+ mode: "all",
62
+ resolver: zodResolver(LocationAdministrationSchema),
63
+ defaultValues: {
64
+ name: initialData.name || "",
65
+ tags: initialData.tags || [],
66
+ },
67
+ });
68
+
69
+ const onSubmit = (formData: locationData) => {
70
+ const formDataFormSubmission = getValues();
71
+ const locationTagsUuid =
72
+ formDataFormSubmission?.tags?.["selectedItems"]?.map((tag) => tag.uuid) ??
73
+ [];
74
+
75
+ const payload = {
76
+ name: formDataFormSubmission.name,
77
+ tags: locationTagsUuid,
78
+ };
79
+ const result = LocationAdministrationSchema.safeParse(formData);
80
+ if (result.success) {
81
+ setShowErrorNotification(false);
82
+ handleCreateQuestion(payload);
83
+ }
84
+ };
85
+
86
+ const onError = (error: { [key: string]: ErrorType }) => {
87
+ setFormStateError(Object.entries(error)[0][1].message);
88
+ setShowErrorNotification(true);
89
+ };
90
+
91
+ return (
92
+ <ComposedModal
93
+ open={showModal}
94
+ onClose={() => onModalChange(false)}
95
+ preventCloseOnClickOutside
96
+ size={"md"}
97
+ >
98
+ <ModalHeader title={headerTitle} />
99
+ <form onSubmit={handleSubmit(onSubmit, onError)}>
100
+ <ModalBody hasScrollingContent>
101
+ <Stack gap={3}>
102
+ <FormGroup legendText={""}>
103
+ <Controller
104
+ name="name"
105
+ control={control}
106
+ rules={{ required: true }}
107
+ render={({ field, fieldState }) => (
108
+ <>
109
+ <TextInput
110
+ id="location"
111
+ labelText={t("location", "Location Name")}
112
+ placeholder={t("locationPlaceholder", "Add a location")}
113
+ invalidText={fieldState.error?.message}
114
+ {...field}
115
+ />
116
+ </>
117
+ )}
118
+ />
119
+ <div className={styles.loaderContainer}>
120
+ <Controller
121
+ name="tags"
122
+ control={control}
123
+ render={({ field, fieldState }) => (
124
+ <FilterableMultiSelect
125
+ id="tag"
126
+ titleText="Select tag(s)"
127
+ helperText="This is helper text"
128
+ items={Tags ?? []}
129
+ {...field}
130
+ itemToString={(item) => (item ? item.display : "")}
131
+ selectionFeedback="top-after-reopen"
132
+ />
133
+ )}
134
+ />
135
+ </div>
136
+ </FormGroup>
137
+
138
+ {showErrorNotification && (
139
+ <InlineNotification
140
+ lowContrast
141
+ title={t("error", "Error")}
142
+ style={{ minWidth: "100%", margin: "0rem", padding: "0rem" }}
143
+ role="alert"
144
+ kind="error"
145
+ subtitle={t("pleaseFillField", formStateError) + "."}
146
+ onClose={() => setShowErrorNotification(false)}
147
+ />
148
+ )}
149
+ </Stack>
150
+ </ModalBody>
151
+ <ModalFooter>
152
+ <Button onClick={() => onModalChange(false)} kind="secondary">
153
+ {t("cancel", "Cancel")}
154
+ </Button>
155
+ <Button disabled={!isDirty} type="submit">
156
+ <span>{t("save", "Save")}</span>
157
+ </Button>
158
+ </ModalFooter>
159
+ </form>
160
+ </ComposedModal>
161
+ );
162
+ };
163
+
164
+ export default LocationAdministrationForm;
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useMemo, useState } from "react";
2
2
  import { useStockLocationPages } from "./stock-locations-table.resource";
3
3
  import {
4
4
  Button,
@@ -12,6 +12,9 @@ import styles from "../stock-items/stock-items-table.scss";
12
12
  import { ResourceRepresentation } from "../core/api/api";
13
13
  import DataList from "../core/components/table/table.component";
14
14
  import { useTranslation } from "react-i18next";
15
+ import { mutate } from "swr";
16
+ import NewLocationForm from "./add-locations-form.component";
17
+ import { Add } from "@carbon/react/icons";
15
18
 
16
19
  interface StockLocationsTableProps {
17
20
  status?: string;
@@ -20,20 +23,29 @@ interface StockLocationsTableProps {
20
23
  const StockLocationsItems: React.FC<StockLocationsTableProps> = () => {
21
24
  const { t } = useTranslation();
22
25
 
23
- const { tableHeaders, tableRows, items, isLoadingLocations } =
24
- useStockLocationPages({
25
- v: ResourceRepresentation.Full,
26
- });
26
+ const [showLocationModal, setAddLocationModal] = useState(false);
27
+
28
+ const { tableHeaders, tableRows, items, isLoading } = useStockLocationPages({
29
+ v: ResourceRepresentation.Full,
30
+ });
27
31
 
28
32
  const handleRefresh = () => {
29
33
  // search.refetch()
30
34
  };
31
35
 
32
- const createStockItem = () => {
33
- // search.refetch()
36
+ const createStockLocation = () => {
37
+ {
38
+ showLocationModal ? (
39
+ <NewLocationForm
40
+ onModalChange={setAddLocationModal}
41
+ showModal={showLocationModal}
42
+ mutate={mutate}
43
+ />
44
+ ) : null;
45
+ }
34
46
  };
35
47
 
36
- if (isLoadingLocations) {
48
+ if (isLoading) {
37
49
  return <DataTableSkeleton role="progressbar" />;
38
50
  }
39
51
 
@@ -48,8 +60,19 @@ const StockLocationsItems: React.FC<StockLocationsTableProps> = () => {
48
60
  Refresh
49
61
  </TableToolbarAction>
50
62
  </TableToolbarMenu>
51
- <Button onClick={createStockItem} size="md" kind="primary">
52
- {t("stockmanagement.addnewlocation", "Add Location")}
63
+ {showLocationModal ? (
64
+ <NewLocationForm
65
+ onModalChange={setAddLocationModal}
66
+ showModal={showLocationModal}
67
+ mutate={mutate}
68
+ />
69
+ ) : null}
70
+ <Button
71
+ kind="ghost"
72
+ renderIcon={(props) => <Add size={16} {...props} />}
73
+ onClick={() => setAddLocationModal(true)}
74
+ >
75
+ {t("createLocation", "Create Location")}
53
76
  </Button>
54
77
  </>
55
78
  )}
@@ -1,12 +1,22 @@
1
1
  import { StockOperationFilter } from "../stock-operations/stock-operations.resource";
2
2
  import { useMemo, useState } from "react";
3
- import { usePagination } from "@openmrs/esm-framework";
3
+ import {
4
+ FetchResponse,
5
+ openmrsFetch,
6
+ restBaseUrl,
7
+ showToast,
8
+ usePagination,
9
+ } from "@openmrs/esm-framework";
4
10
  import { useTranslation } from "react-i18next";
5
- import { useStockLocations } from "../stock-lookups/stock-lookups.resource";
11
+ import {
12
+ useStockLocations,
13
+ useStockTagLocations,
14
+ } from "../stock-lookups/stock-lookups.resource";
15
+ import useSWR from "swr";
16
+ import { extractErrorMessagesFromResponse } from "../constants";
6
17
 
7
18
  export function useStockLocationPages(filter: StockOperationFilter) {
8
- const { locations, isErrorLocation, isLoadingLocations } =
9
- useStockLocations(filter);
19
+ const { stockLocations, error, isLoading } = useStockTagLocations();
10
20
 
11
21
  const pageSizes = [10, 20, 30, 40, 50];
12
22
  const [currentPageSize, setPageSize] = useState(10);
@@ -15,7 +25,7 @@ export function useStockLocationPages(filter: StockOperationFilter) {
15
25
  goTo,
16
26
  results: paginatedQueueEntries,
17
27
  currentPage,
18
- } = usePagination(locations.results, currentPageSize);
28
+ } = usePagination(stockLocations, currentPageSize);
19
29
 
20
30
  const { t } = useTranslation();
21
31
 
@@ -46,28 +56,73 @@ export function useStockLocationPages(filter: StockOperationFilter) {
46
56
  );
47
57
 
48
58
  const tableRows = useMemo(() => {
49
- return locations?.results?.map((location) => ({
59
+ return stockLocations.map((location) => ({
50
60
  id: location?.uuid,
51
61
  key: `key-${location?.uuid}`,
52
62
  uuid: `${location?.uuid}`,
53
63
  name: `${location?.name}`,
54
- tags: location?.tags?.map((p) => p.display)?.join(", ") ?? "",
64
+ tags:
65
+ location?.meta.tag
66
+ ?.filter((tag) => tag.code !== "SUBSETTED")
67
+ .map((p) => p.code)
68
+ ?.join(", ") ?? "",
55
69
  childLocations:
56
70
  location?.childLocations?.map((p) => p.display)?.join(", ") ?? "",
57
71
  }));
58
- }, [locations?.results]);
59
-
72
+ }, [stockLocations]);
60
73
  return {
61
- items: locations.results,
74
+ items: stockLocations,
62
75
  currentPage,
63
76
  currentPageSize,
64
77
  paginatedQueueEntries,
65
78
  goTo,
66
79
  pageSizes,
67
- isLoadingLocations,
68
- isErrorLocation,
80
+ isLoading,
81
+ error,
69
82
  setPageSize,
70
83
  tableHeaders,
71
84
  tableRows,
72
85
  };
73
86
  }
87
+
88
+ export const useLocationTags = () => {
89
+ const url = `${restBaseUrl}/locationtag/`;
90
+
91
+ // eslint-disable-next-line react-hooks/rules-of-hooks
92
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
93
+ { data },
94
+ Error
95
+ >(url, openmrsFetch);
96
+ const results = data?.data?.results ? data?.data?.results : [];
97
+ return {
98
+ locationTagList: results,
99
+ loading: isLoading,
100
+ mutate,
101
+ };
102
+ };
103
+ interface LocationName {
104
+ name: string;
105
+ }
106
+ export async function saveLocation({
107
+ locationPayload,
108
+ }): Promise<FetchResponse<LocationName>> {
109
+ try {
110
+ const response: FetchResponse = await openmrsFetch(
111
+ `${restBaseUrl}/location/`,
112
+ {
113
+ method: "POST",
114
+ headers: { "Content-Type": "application/json" },
115
+ body: locationPayload,
116
+ }
117
+ );
118
+ return response;
119
+ } catch (error) {
120
+ const errorMessages = extractErrorMessagesFromResponse(error);
121
+ showToast({
122
+ description: errorMessages.join(", "),
123
+ title: "Error on saving form",
124
+ kind: "error",
125
+ critical: true,
126
+ });
127
+ }
128
+ }
@@ -0,0 +1,3 @@
1
+ .loaderContainer {
2
+ margin-bottom: 150px;
3
+ }
@@ -178,7 +178,7 @@ export function useUsers(filter: UserFilterCriteria) {
178
178
 
179
179
  // getUser
180
180
  export function useUser(id: string) {
181
- const apiUrl = `${restBaseUrl}/user${id}`;
181
+ const apiUrl = `${restBaseUrl}/user/${id}`;
182
182
  const { data, error, isLoading } = useSWR<
183
183
  {
184
184
  data: User;
@@ -22,7 +22,12 @@ import StockOperationApproveDispatchButton from "../stock-operations-dialog/stoc
22
22
  import StockOperationCompleteDispatchButton from "../stock-operations-dialog/stock-operations-completed-dispatch-button.component";
23
23
  import StockOperationIssueStockButton from "../stock-operations-dialog/stock-operations-issue-stock-button.component";
24
24
  import { StockOperation } from "./stock-operation-context/useStockOperationContext";
25
- import { formatDate, parseDate, showToast } from "@openmrs/esm-framework";
25
+ import {
26
+ formatDate,
27
+ parseDate,
28
+ showSnackbar,
29
+ showToast,
30
+ } from "@openmrs/esm-framework";
26
31
  import {
27
32
  OperationType,
28
33
  StockOperationType,
@@ -43,18 +48,17 @@ const AddStockOperation: React.FC<AddStockOperationProps> = (props) => {
43
48
  if (isLoading) return <AccordionSkeleton />;
44
49
  if (isError) {
45
50
  closeOverlay();
46
- showToast({
51
+ showSnackbar({
47
52
  kind: "error",
48
53
  title: t("error", "Error"),
49
- description: t("errorLoadingStockOperation", "Error loading stock item"),
50
- millis: 5000,
51
- critical: true,
54
+ subtitle: t("errorLoadingStockOperation", "Error loading stock item"),
55
+ timeoutInMs: 5000,
56
+ isLowContrast: true,
52
57
  });
53
58
  return;
54
59
  }
55
60
 
56
61
  let operations: StockOperationType[] | null | undefined;
57
-
58
62
  const tabs: TabItem[] = [
59
63
  {
60
64
  name: isEditing
@@ -81,7 +85,7 @@ const AddStockOperation: React.FC<AddStockOperationProps> = (props) => {
81
85
  setManageStockItems(true);
82
86
  setSelectedIndex(1);
83
87
  }}
84
- operation={props.operation}
88
+ operation={props?.operation}
85
89
  />
86
90
  ),
87
91
  },
@@ -119,7 +123,13 @@ const AddStockOperation: React.FC<AddStockOperationProps> = (props) => {
119
123
  setup={result}
120
124
  canEdit={canEdit}
121
125
  locked={false}
122
- model={isEditing ? props?.model : result?.dto}
126
+ model={
127
+ isEditing
128
+ ? props?.model
129
+ : props?.operation?.name === "Stock Issue"
130
+ ? props?.model
131
+ : result?.dto
132
+ }
123
133
  requiresDispatchAcknowledgement={
124
134
  isEditing
125
135
  ? props?.model?.operationType === "return" ||
@@ -58,7 +58,6 @@ function shouldDeleteDestinationUuid(operationType) {
58
58
 
59
59
  export function createBaseOperationPayload(model, item, operationType) {
60
60
  const req = Object.assign(model, item);
61
-
62
61
  const propertiesToDelete = [
63
62
  "submitted",
64
63
  "cancelledByFamilyName",
@@ -105,6 +104,5 @@ export function createBaseOperationPayload(model, item, operationType) {
105
104
  if (shouldDeleteDestinationUuid(operationType)) {
106
105
  delete req.destinationUuid;
107
106
  }
108
-
109
107
  return req;
110
108
  }
@@ -36,10 +36,7 @@ import rootStyles from "../../root.scss";
36
36
  import { ResourceRepresentation } from "../../core/api/api";
37
37
  import { useStockOperationPages } from "../stock-operations-table.resource";
38
38
  import { useStockOperationContext } from "./stock-operation-context/useStockOperationContext";
39
- import {
40
- createBaseOperationPayload,
41
- getRequisitionStockOperations,
42
- } from "./add-stock-utils";
39
+ import { createBaseOperationPayload } from "./add-stock-utils";
43
40
 
44
41
  interface BaseOperationDetailsProps {
45
42
  isEditing?: boolean;
@@ -70,8 +67,8 @@ const BaseOperationDetails: React.FC<BaseOperationDetailsProps> = ({
70
67
  v: ResourceRepresentation.Full,
71
68
  totalCount: true,
72
69
  });
73
- const requisitionStockOperations = getRequisitionStockOperations(items);
74
- const operationType = operationFromString(operation.operationType);
70
+ const operationType = operationFromString(operation?.operationType);
71
+ const issueStockOperation = mapIssueStockLocations(model);
75
72
 
76
73
  const {
77
74
  handleSubmit,
@@ -79,7 +76,7 @@ const BaseOperationDetails: React.FC<BaseOperationDetailsProps> = ({
79
76
  formState: { errors },
80
77
  setValue,
81
78
  } = useForm<StockOperationFormData>({
82
- defaultValues: model,
79
+ defaultValues: operationType === "stockissue" ? issueStockOperation : model,
83
80
  mode: "all",
84
81
  resolver: zodResolver(operationSchema(operationType)),
85
82
  });
@@ -112,34 +109,6 @@ const BaseOperationDetails: React.FC<BaseOperationDetailsProps> = ({
112
109
  <form
113
110
  className={`${rootStyles.formContainer} ${rootStyles.verticalForm}`}
114
111
  >
115
- {operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE && (
116
- <Controller
117
- control={control}
118
- name="requisitionStockOperationUuid"
119
- render={({ field }) => (
120
- <ComboBox
121
- id="requisitionStockOperationUuid"
122
- items={requisitionStockOperations}
123
- onChange={(data: { selectedItem: StockOperationDTO }) => {
124
- field.onChange(data.selectedItem.uuid);
125
- Object.assign(
126
- model.stockOperationItems,
127
- data.selectedItem.stockOperationItems
128
- );
129
- setFormContext({
130
- stockItems: data.selectedItem.stockOperationItems,
131
- });
132
- }}
133
- itemToString={(item) => `${item?.operationNumber}` ?? ""}
134
- titleText={t("requisitionStockOperation", "Requisition")}
135
- invalid={!!errors.requisitionStockOperationUuid}
136
- invalidText={errors.requisitionStockOperationUuid?.message}
137
- placeholder={t("chooseARequisition", "Choose a requisition")}
138
- />
139
- )}
140
- />
141
- )}
142
-
143
112
  {canEdit && (
144
113
  <Controller
145
114
  control={control}
@@ -210,7 +179,11 @@ const BaseOperationDetails: React.FC<BaseOperationDetailsProps> = ({
210
179
  {(!canEdit || isEditing || lockSource) && (
211
180
  <TextInput
212
181
  id="sourceUuidLbl"
213
- value={model?.sourceName ?? ""}
182
+ value={
183
+ operationType === "stockissue"
184
+ ? issueStockOperation.sourceName
185
+ : model?.sourceName ?? ""
186
+ }
214
187
  readOnly={true}
215
188
  labelText={operation?.hasDestination ? "From" : "From"}
216
189
  />
@@ -237,7 +210,11 @@ const BaseOperationDetails: React.FC<BaseOperationDetailsProps> = ({
237
210
  {(!canEdit || isEditing || lockDestination) && (
238
211
  <TextInput
239
212
  id="destinationUuidLbl"
240
- value={model?.destinationName ?? ""}
213
+ value={
214
+ operationType === "stockissue"
215
+ ? issueStockOperation.destinationName
216
+ : model?.destinationName ?? ""
217
+ }
241
218
  readOnly={true}
242
219
  labelText={operation?.hasSource ? "To" : "To"}
243
220
  />
@@ -348,5 +325,19 @@ const BaseOperationDetails: React.FC<BaseOperationDetailsProps> = ({
348
325
  </div>
349
326
  );
350
327
  };
328
+ function mapIssueStockLocations(stockOperation) {
329
+ /** Since we are using requisition information to issue stock,
330
+ please note that the locations will be inverted: the destination listed on the requisition will become the issuing location.
331
+ */
332
+ const { sourceUuid, sourceName, destinationUuid, destinationName } =
333
+ stockOperation;
334
+ return {
335
+ ...stockOperation,
336
+ sourceUuid: destinationUuid,
337
+ sourceName: destinationName,
338
+ destinationUuid: sourceUuid,
339
+ destinationName: sourceName,
340
+ };
341
+ }
351
342
 
352
343
  export default BaseOperationDetails;
@@ -2,6 +2,7 @@ import { closeOverlay, launchOverlay } from "../core/components/overlay/hook";
2
2
  import React from "react";
3
3
  import {
4
4
  FetchResponse,
5
+ restBaseUrl,
5
6
  showModal,
6
7
  showNotification,
7
8
  showToast,
@@ -12,7 +13,10 @@ import {
12
13
  updateStockOperation,
13
14
  } from "./stock-operations.resource";
14
15
  import AddStockOperation from "./add-stock-operation/add-stock-operation.component";
15
- import { StockOperationType } from "../core/api/types/stockOperation/StockOperationType";
16
+ import {
17
+ OperationType,
18
+ StockOperationType,
19
+ } from "../core/api/types/stockOperation/StockOperationType";
16
20
  import { useLocation } from "react-router-dom";
17
21
  import { extractErrorMessagesFromResponse } from "../constants";
18
22
  import { handleMutate } from "./swr-revalidation";
@@ -28,12 +32,23 @@ export const addOrEditStockOperation = async (
28
32
  if (operation.operationType === "requisition") {
29
33
  delete payload.destinationName;
30
34
  }
35
+ if (operation.operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE) {
36
+ const stockIssueOpsTypeUuid = "66666666-6666-6666-6666-666666666666";
37
+ delete payload.completedDate;
38
+ delete payload.completedBy;
39
+ delete payload.completedByFamilyName;
40
+ delete payload.completedByGivenName;
41
+ delete payload.operationTypeUuid;
42
+ delete payload.permission;
43
+ delete payload.locked;
44
+ payload["operationTypeUuid"] = stockIssueOpsTypeUuid;
45
+ }
31
46
  const response: FetchResponse<StockOperationDTO> = await (isEditing
32
47
  ? updateStockOperation
33
48
  : createStockOperation)(payload);
34
49
 
35
50
  if (response?.data) {
36
- handleMutate("ws/rest/v1/stockmanagement/stockoperation");
51
+ handleMutate(`${restBaseUrl}/stockmanagement/stockoperation`);
37
52
  showToast({
38
53
  critical: true,
39
54
  title: `${isEditing ? "Edit" : "Add"} Stock Operation`,
@@ -16,9 +16,10 @@ import {
16
16
  StopOperationActionType,
17
17
  } from "../../core/api/types/stockOperation/StockOperationAction";
18
18
  import { executeStockOperationAction } from "../stock-operations.resource";
19
- import { showNotification, showToast } from "@openmrs/esm-framework";
19
+ import { restBaseUrl, showSnackbar } from "@openmrs/esm-framework";
20
20
  import { closeOverlay } from "../../core/components/overlay/hook";
21
21
  import { extractErrorMessagesFromResponse } from "../../constants";
22
+ import { handleMutate } from "../swr-revalidation";
22
23
 
23
24
  interface StockOperationDialogProps {
24
25
  title: string;
@@ -92,28 +93,27 @@ const StockOperationDialog: React.FC<StockOperationDialogProps> = ({
92
93
  executeStockOperationAction(payload).then(
93
94
  () => {
94
95
  setIsApproving(false);
95
- showToast({
96
- critical: true,
96
+ showSnackbar({
97
97
  title: t("title", `${title} Operation`),
98
- kind: "success",
99
- description: t(
98
+ subtitle: t(
100
99
  "successMessage",
101
100
  `You have successfully ${title} operation `
102
101
  ),
103
- });
104
- closeModal();
102
+ kind: "success",
103
+ }),
104
+ closeModal();
105
105
  closeOverlay();
106
+ handleMutate(`${restBaseUrl}/stockmanagement/stockoperation`);
106
107
  },
107
108
  (err) => {
108
109
  setIsApproving(false);
109
110
  const errorMessages = extractErrorMessagesFromResponse(err);
110
- showNotification({
111
- description: t("errorDescription", errorMessages.join(", ")),
111
+ showSnackbar({
112
112
  title: t("errorDescriptionTitle", "Error on saving form"),
113
+ subtitle: t("errorDescription", errorMessages.join(", ")),
113
114
  kind: "error",
114
- critical: true,
115
- });
116
- closeModal();
115
+ }),
116
+ closeModal();
117
117
  closeOverlay();
118
118
  }
119
119
  );
@@ -20,7 +20,7 @@ const StockOperationIssueStockButton: React.FC<
20
20
  uuid: "",
21
21
  name: "Stock Issue",
22
22
  description: "",
23
- operationType: "",
23
+ operationType: "stockissue",
24
24
  hasSource: false,
25
25
  sourceType: "Location",
26
26
  hasDestination: false,
@@ -40,8 +40,9 @@ const StockOperationIssueStockButton: React.FC<
40
40
  voided: false,
41
41
  };
42
42
 
43
+ const modifiedOperation = addRequisitionStockOperation(operation);
43
44
  const handleButtonClick = () => {
44
- launchAddOrEditDialog(operation, false, type, operations, false);
45
+ launchAddOrEditDialog(modifiedOperation, false, type, operations, false);
45
46
  };
46
47
 
47
48
  return (
@@ -54,5 +55,12 @@ const StockOperationIssueStockButton: React.FC<
54
55
  </Button>
55
56
  );
56
57
  };
58
+ function addRequisitionStockOperation(stockOperation) {
59
+ const { uuid } = stockOperation;
60
+ return {
61
+ ...stockOperation,
62
+ requisitionStockOperationUuid: uuid,
63
+ };
64
+ }
57
65
 
58
66
  export default StockOperationIssueStockButton;