@openmrs/esm-stock-management-app 1.0.1-pre.777 → 1.0.1-pre.785

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/__mocks__/index.ts +1 -0
  2. package/__mocks__/operation-type.mock.ts +532 -0
  3. package/dist/155.js +1 -0
  4. package/dist/155.js.map +1 -0
  5. package/dist/172.js +1 -1
  6. package/dist/20.js +1 -1
  7. package/dist/290.js +1 -1
  8. package/dist/493.js +2 -0
  9. package/dist/493.js.map +1 -0
  10. package/dist/606.js +1 -1
  11. package/dist/627.js +1 -1
  12. package/dist/{400.js → 914.js} +1 -1
  13. package/dist/914.js.map +1 -0
  14. package/dist/main.js +1 -1
  15. package/dist/main.js.map +1 -1
  16. package/dist/openmrs-esm-stock-management-app.js +1 -1
  17. package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +81 -57
  18. package/dist/openmrs-esm-stock-management-app.js.map +1 -1
  19. package/dist/routes.json +1 -1
  20. package/package.json +1 -1
  21. package/src/core/utils/utils.ts +29 -0
  22. package/src/index.ts +4 -0
  23. package/src/routes.json +9 -0
  24. package/src/stock-items/add-stock-item/transactions/printout/transactions-stockcard-printout.component.tsx +8 -12
  25. package/src/stock-items/add-stock-item/transactions/transactions.component.tsx +8 -12
  26. package/src/stock-items/stock-items.resource.ts +5 -5
  27. package/src/stock-lookups/stock-lookups.resource.ts +2 -2
  28. package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx +41 -16
  29. package/src/stock-operations/{add-stock-operation/received-items.component.tsx → received-items.component.tsx} +1 -1
  30. package/src/stock-operations/stock-operation-reference.component.tsx +64 -0
  31. package/src/stock-operations/stock-operation-status/stock-operation-status-row.tsx +77 -0
  32. package/src/stock-operations/stock-operation-status/stock-operation-status.scss +32 -0
  33. package/src/stock-operations/stock-operation-status/stock-operation-status.tsx +45 -0
  34. package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +30 -29
  35. package/src/stock-operations/stock-operation.utils.tsx +16 -79
  36. package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +27 -39
  37. package/src/stock-operations/stock-operations-dialog/stock-operations-print-button.component.tsx +51 -59
  38. package/src/stock-operations/{stock-item-selector/stock-item-selector.resource.tsx → stock-operations-forms/hooks/useFilterableStockItems.ts} +4 -4
  39. package/src/stock-operations/stock-operations-forms/hooks/useFilteredOperationTypesByRoles.ts +30 -0
  40. package/src/stock-operations/stock-operations-forms/hooks/useOperationTypePermisions.ts +29 -0
  41. package/src/stock-operations/stock-operations-forms/hooks/useParties.ts +73 -0
  42. package/src/stock-operations/{users-selector/users-selector.resource.tsx → stock-operations-forms/hooks/useSearchUser.ts} +9 -7
  43. package/src/stock-operations/{batch-no-selector/batch-no-selector.resource.tsx → stock-operations-forms/hooks/useStockItemBatchNumbers.ts} +3 -3
  44. package/src/stock-operations/stock-operations-forms/hooks/useStockOperationLinks.ts +20 -0
  45. package/src/stock-operations/stock-operations-forms/input-components/batch-no-selector.component.tsx +72 -0
  46. package/src/stock-operations/stock-operations-forms/input-components/batch-no-selector.test.tsx +90 -0
  47. package/src/stock-operations/{add-stock-operation/stock-item-search/stock-item-search.scss → stock-operations-forms/input-components/input-components-styles.scss} +2 -2
  48. package/src/stock-operations/stock-operations-forms/input-components/qty-uim-selector.test.tsx +157 -0
  49. package/src/stock-operations/stock-operations-forms/input-components/quantity-uom-selector.component.tsx +53 -0
  50. package/src/stock-operations/stock-operations-forms/input-components/stock-item-search.component.tsx +56 -0
  51. package/src/stock-operations/stock-operations-forms/input-components/stock-operation-reason-selector.component.tsx +59 -0
  52. package/src/stock-operations/stock-operations-forms/input-components/stock-operation-reason-selector.test.tsx +216 -0
  53. package/src/stock-operations/stock-operations-forms/input-components/unique-batch-no-entry-input.component.tsx +59 -0
  54. package/src/stock-operations/stock-operations-forms/input-components/user-selector.test.tsx +110 -0
  55. package/src/stock-operations/stock-operations-forms/input-components/users-selector.component.tsx +111 -0
  56. package/src/stock-operations/stock-operations-forms/step1.test.tsx +303 -0
  57. package/src/stock-operations/stock-operations-forms/step2.test.tsx +250 -0
  58. package/src/stock-operations/stock-operations-forms/step3.test.tsx +223 -0
  59. package/src/stock-operations/stock-operations-forms/steps/base-operation-details-form-step.tsx +241 -0
  60. package/src/stock-operations/stock-operations-forms/steps/quantity-uom-cell.component.tsx +33 -0
  61. package/src/stock-operations/stock-operations-forms/steps/stock-availability-cell.component.tsx +51 -0
  62. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-batch-no-cell.component.tsx +40 -0
  63. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-cell.component.tsx +38 -0
  64. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-expiry-cell.component.tsx +41 -0
  65. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.component.tsx +281 -0
  66. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.scc.scss +64 -0
  67. package/src/stock-operations/stock-operations-forms/steps/stock-operation-submission-form-step.component.tsx +236 -0
  68. package/src/stock-operations/stock-operations-forms/stock-issue-form-initializer-with-related-requisition-operation.component.tsx +55 -0
  69. package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.scss +41 -0
  70. package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.workspace.tsx +197 -0
  71. package/src/stock-operations/stock-operations-forms/stock-operation-form-header.component.tsx +166 -0
  72. package/src/stock-operations/stock-operations-forms/stock-operation-form.component.tsx +200 -0
  73. package/src/stock-operations/stock-operations-forms/stock-operation-form.scss +111 -0
  74. package/src/stock-operations/stock-operations-forms/stock-operation-related-link.component.tsx +45 -0
  75. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stepper.scss +41 -0
  76. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stock-operation-stepper.component.tsx +52 -0
  77. package/src/stock-operations/stock-operations-forms/stock-operations-form-utils.ts +32 -0
  78. package/src/stock-operations/stock-operations-table.component.tsx +20 -56
  79. package/src/stock-operations/stock-operations.resource.ts +16 -13
  80. package/src/stock-operations/validation-schema.ts +72 -14
  81. package/dist/400.js.map +0 -1
  82. package/dist/766.js +0 -2
  83. package/dist/766.js.map +0 -1
  84. package/src/stock-operations/add-stock-operation/add-stock-operation.component.tsx +0 -349
  85. package/src/stock-operations/add-stock-operation/add-stock-operation.resource.tsx +0 -27
  86. package/src/stock-operations/add-stock-operation/add-stock-operation.scss +0 -60
  87. package/src/stock-operations/add-stock-operation/add-stock-operation.test.tsx +0 -192
  88. package/src/stock-operations/add-stock-operation/add-stock-operation.utils.tsx +0 -152
  89. package/src/stock-operations/add-stock-operation/add-stock-utils.ts +0 -103
  90. package/src/stock-operations/add-stock-operation/base-operation-details.component.tsx +0 -439
  91. package/src/stock-operations/add-stock-operation/base-operation-details.scss +0 -30
  92. package/src/stock-operations/add-stock-operation/stock-item-search/stock-item-search.component.tsx +0 -70
  93. package/src/stock-operations/add-stock-operation/stock-items-addition-row.component.tsx +0 -360
  94. package/src/stock-operations/add-stock-operation/stock-items-addition-row.resource.tsx +0 -0
  95. package/src/stock-operations/add-stock-operation/stock-items-addition-row.scss +0 -12
  96. package/src/stock-operations/add-stock-operation/stock-items-addition-row.test.tsx +0 -10
  97. package/src/stock-operations/add-stock-operation/stock-items-addition.component.scss +0 -17
  98. package/src/stock-operations/add-stock-operation/stock-items-addition.component.tsx +0 -254
  99. package/src/stock-operations/add-stock-operation/stock-operation-context/useStockOperationContext.tsx +0 -16
  100. package/src/stock-operations/add-stock-operation/stock-operation-reference.component.tsx +0 -39
  101. package/src/stock-operations/add-stock-operation/stock-operation-related-link.component.tsx +0 -38
  102. package/src/stock-operations/add-stock-operation/stock-operation-status.component.tsx +0 -170
  103. package/src/stock-operations/add-stock-operation/stock-operation-submission.component.tsx +0 -189
  104. package/src/stock-operations/add-stock-operation/stock-operation-submission.test.tsx +0 -138
  105. package/src/stock-operations/add-stock-operation/types.ts +0 -55
  106. package/src/stock-operations/add-stock-operation/validationSchema.ts +0 -54
  107. package/src/stock-operations/batch-no-selector/batch-no-selector.component.tsx +0 -114
  108. package/src/stock-operations/batch-no-selector/batch-no-selector.scss +0 -0
  109. package/src/stock-operations/batch-no-selector/batch-no-selector.test.tsx +0 -101
  110. package/src/stock-operations/party-selector/party-selector.component.tsx +0 -59
  111. package/src/stock-operations/qty-uom-selector/qty-uom-selector.component.tsx +0 -65
  112. package/src/stock-operations/qty-uom-selector/qty-uom-selector.resource.tsx +0 -0
  113. package/src/stock-operations/qty-uom-selector/qty-uom-selector.scss +0 -0
  114. package/src/stock-operations/qty-uom-selector/qty-uom-selector.test.tsx +0 -10
  115. package/src/stock-operations/stock-item-selector/stock-item-selector.component.tsx +0 -69
  116. package/src/stock-operations/stock-item-selector/stock-item-selector.scss +0 -0
  117. package/src/stock-operations/stock-item-selector/stock-item-selector.test.tsx +0 -10
  118. package/src/stock-operations/stock-operation-reason-selector/stock-operation-reason-selector.component.tsx +0 -62
  119. package/src/stock-operations/users-selector/users-selector.component.tsx +0 -75
  120. /package/dist/{766.js.LICENSE.txt → 493.js.LICENSE.txt} +0 -0
@@ -1,33 +1,58 @@
1
- import React from 'react';
2
- import { Button } from '@carbon/react';
1
+ import { Button, InlineLoading } from '@carbon/react';
3
2
  import { Edit } from '@carbon/react/icons';
3
+ import { showSnackbar } from '@openmrs/esm-framework';
4
+ import React, { useCallback, useEffect, useMemo } from 'react';
4
5
  import { useTranslation } from 'react-i18next';
5
6
  import { StockOperationDTO } from '../../core/api/types/stockOperation/StockOperationDTO';
6
- import { StockOperationType } from '../../core/api/types/stockOperation/StockOperationType';
7
- import { launchAddOrEditDialog } from '../stock-operation.utils';
7
+ import { launchStockoperationAddOrEditDialog } from '../stock-operation.utils';
8
+ import useFilteredOperationTypesByRoles from '../stock-operations-forms/hooks/useFilteredOperationTypesByRoles';
9
+ import { useStockOperationAndItems } from '../stock-operations.resource';
8
10
 
9
11
  interface EditStockOperationActionMenuProps {
10
- model: StockOperationDTO;
11
- operations: StockOperationType[];
12
- operationUuid: string;
13
- operationNumber: string;
14
- onEdit: (operation: StockOperationDTO) => void;
12
+ stockOperation: StockOperationDTO;
15
13
  showIcon?: boolean;
16
14
  showprops?: boolean;
17
15
  }
18
16
 
19
17
  const EditStockOperationActionMenu: React.FC<EditStockOperationActionMenuProps> = ({
20
- model,
21
- operations,
18
+ stockOperation: _stockOperation,
22
19
  showIcon = true,
23
20
  showprops = true,
24
21
  }) => {
25
22
  const { t } = useTranslation();
23
+ const { error, isLoading, operationTypes } = useFilteredOperationTypesByRoles();
24
+ const {
25
+ isLoading: isLoadingStockoperation,
26
+ items: stockOperation,
27
+ error: stockOperationError,
28
+ } = useStockOperationAndItems(_stockOperation.uuid);
29
+ const activeOperationType = useMemo(
30
+ () => operationTypes?.find((op) => op?.uuid === stockOperation?.operationTypeUuid),
31
+ [operationTypes, stockOperation],
32
+ );
33
+
34
+ const handleEdit = useCallback(() => {
35
+ launchStockoperationAddOrEditDialog(
36
+ t,
37
+ activeOperationType,
38
+ stockOperation,
39
+ stockOperation?.requisitionStockOperationUuid,
40
+ );
41
+ }, [t, activeOperationType, stockOperation]);
42
+
43
+ useEffect(() => {
44
+ if (error) {
45
+ showSnackbar({
46
+ kind: 'error',
47
+ title: t('stockOperationError', 'Error loading stock operation types'),
48
+ subtitle: error?.message ?? stockOperationError?.message,
49
+ });
50
+ }
51
+ }, [error, t, stockOperationError]);
52
+
53
+ if (isLoading || isLoadingStockoperation) return <InlineLoading status="active" iconDescription="Loading" />;
26
54
 
27
- const handleEdit = () => {
28
- const operation = operations?.find((op) => op?.uuid === model?.operationTypeUuid);
29
- launchAddOrEditDialog(t, model, true, operation, operations, false);
30
- };
55
+ if (error || stockOperationError) return <>--</>;
31
56
 
32
57
  return (
33
58
  <Button
@@ -37,7 +62,7 @@ const EditStockOperationActionMenu: React.FC<EditStockOperationActionMenuProps>
37
62
  iconDescription={t('editStockOperation', 'Edit Stock Operation')}
38
63
  renderIcon={showIcon ? Edit : undefined}
39
64
  >
40
- {showprops && model?.operationNumber}
65
+ {showprops && stockOperation?.operationNumber}
41
66
  </Button>
42
67
  );
43
68
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
- import { StockOperationDTO } from '../../core/api/types/stockOperation/StockOperationDTO';
3
+ import { StockOperationDTO } from '../core/api/types/stockOperation/StockOperationDTO';
4
4
  import {
5
5
  DataTable,
6
6
  Table,
@@ -0,0 +1,64 @@
1
+ import { InlineLoading } from '@carbon/react';
2
+ import { showSnackbar } from '@openmrs/esm-framework';
3
+ import React, { useCallback, useEffect } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { useStockOperationTypes } from '../stock-lookups/stock-lookups.resource';
6
+ import { launchStockoperationAddOrEditDialog } from './stock-operation.utils';
7
+ import { useStockOperationAndItems } from './stock-operations.resource';
8
+
9
+ interface StockOperationReferenceProps {
10
+ operationUuid: string;
11
+ operationNumber: string;
12
+ }
13
+
14
+ const StockOperationReference = ({ operationNumber, operationUuid }: StockOperationReferenceProps) => {
15
+ const { t } = useTranslation();
16
+ const { types, isLoading: istypesLoading, error: typesError } = useStockOperationTypes();
17
+ const {
18
+ items: stockOperation,
19
+ error: stockOperationError,
20
+ isLoading: isStockOperationloading,
21
+ } = useStockOperationAndItems(operationUuid ?? null);
22
+
23
+ const handleEdit = useCallback(() => {
24
+ const operationType = types.results?.find((op) => op?.uuid === stockOperation?.operationTypeUuid);
25
+ if (!operationType) {
26
+ return;
27
+ }
28
+ launchStockoperationAddOrEditDialog(
29
+ t,
30
+ operationType,
31
+ stockOperation,
32
+ stockOperation?.requisitionStockOperationUuid,
33
+ );
34
+ }, [stockOperation, t, types.results]);
35
+
36
+ useEffect(() => {
37
+ if (stockOperationError) {
38
+ showSnackbar({
39
+ title: t('errorLoadingStockOperation', 'Error loading stock operation'),
40
+ subtitle: stockOperationError?.message,
41
+ kind: 'error',
42
+ });
43
+ }
44
+ if (typesError) {
45
+ showSnackbar({
46
+ title: t('errorLoadingStockOperationTypes', 'Error loading stock operation types'),
47
+ subtitle: typesError?.message,
48
+ kind: 'error',
49
+ });
50
+ }
51
+ }, [stockOperationError, typesError, t]);
52
+
53
+ if (istypesLoading || isStockOperationloading) {
54
+ return <InlineLoading description={t('loading', 'Loading')} />;
55
+ }
56
+
57
+ return (
58
+ <a onClick={handleEdit} style={{ cursor: 'pointer' }}>
59
+ {operationNumber}
60
+ </a>
61
+ );
62
+ };
63
+
64
+ export default StockOperationReference;
@@ -0,0 +1,77 @@
1
+ import React from 'react';
2
+ import { StockOperationDTO } from '../../core/api/types/stockOperation/StockOperationDTO';
3
+ import styles from './stock-operation-status.scss';
4
+ import StockOpertationStatus from './stock-operation-status';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { Row } from '@carbon/react';
7
+ type Props = {
8
+ stockOperation: StockOperationDTO;
9
+ };
10
+ const StockOperationStatusRow: React.FC<Props> = ({ stockOperation }) => {
11
+ const { t } = useTranslation();
12
+ return (
13
+ <Row className={styles.statusContainerRow}>
14
+ {stockOperation.dateCreated && (
15
+ <StockOpertationStatus
16
+ status={t('started', 'Started')}
17
+ statusFilledDate={stockOperation.dateCreated.toString()}
18
+ statusFillerFamilyName={stockOperation.creatorFamilyName}
19
+ statusFillerGivenName={stockOperation.creatorGivenName}
20
+ />
21
+ )}
22
+ {stockOperation?.submittedDate && (
23
+ <StockOpertationStatus
24
+ status={t('submitted', 'Submitted')}
25
+ statusFilledDate={stockOperation.submittedDate.toString()}
26
+ statusFillerFamilyName={stockOperation.submittedByFamilyName}
27
+ statusFillerGivenName={stockOperation.submittedByGivenName}
28
+ />
29
+ )}
30
+ {stockOperation.dispatchedDate && (
31
+ <StockOpertationStatus
32
+ status={t('dispatched', 'Dispatched')}
33
+ statusFilledDate={stockOperation.dispatchedDate.toString()}
34
+ statusFillerFamilyName={stockOperation.dispatchedByFamilyName}
35
+ statusFillerGivenName={stockOperation.dispatchedByGivenName}
36
+ />
37
+ )}
38
+ {stockOperation.returnedDate && (
39
+ <StockOpertationStatus
40
+ status={t('returned', 'Returned')}
41
+ statusFilledDate={stockOperation.returnedDate.toString()}
42
+ statusFillerFamilyName={stockOperation.returnedByFamilyName}
43
+ statusFillerGivenName={stockOperation.returnedByGivenName}
44
+ extraStatusinfo={<span className={styles.text}>{stockOperation.returnReason}</span>}
45
+ />
46
+ )}
47
+ {stockOperation.completedDate && (
48
+ <StockOpertationStatus
49
+ status={t('completed', 'Completed')}
50
+ statusFilledDate={stockOperation.completedDate.toString()}
51
+ statusFillerFamilyName={stockOperation.completedByFamilyName}
52
+ statusFillerGivenName={stockOperation.completedByGivenName}
53
+ />
54
+ )}
55
+ {stockOperation.status === 'CANCELLED' && (
56
+ <StockOpertationStatus
57
+ status={t('cancelled', 'Cancelled')}
58
+ statusFilledDate={stockOperation.cancelledDate.toString()}
59
+ statusFillerFamilyName={stockOperation.cancelledByFamilyName}
60
+ statusFillerGivenName={stockOperation.cancelledByGivenName}
61
+ extraStatusinfo={<span className={styles.text}>{stockOperation.cancelReason}</span>}
62
+ />
63
+ )}
64
+ {stockOperation.status === 'REJECTED' && (
65
+ <StockOpertationStatus
66
+ status={t('rejected', 'Rejected')}
67
+ statusFilledDate={stockOperation.rejectedDate.toString()}
68
+ statusFillerFamilyName={stockOperation.rejectedByFamilyName}
69
+ statusFillerGivenName={stockOperation.rejectedByGivenName}
70
+ extraStatusinfo={<span>{stockOperation.rejectionReason}</span>}
71
+ />
72
+ )}
73
+ </Row>
74
+ );
75
+ };
76
+
77
+ export default StockOperationStatusRow;
@@ -0,0 +1,32 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+
4
+ .textHeading {
5
+ font-weight: bold;
6
+ }
7
+
8
+ .statusDescriptions {
9
+ margin-top: 4px;
10
+
11
+ .text {
12
+ margin-right: 4px;
13
+ }
14
+ }
15
+
16
+ .statusContainer {
17
+ display: flex;
18
+ margin: 10px;
19
+ gap: layout.$spacing-05;
20
+ flex-direction: column;
21
+ padding: layout.$spacing-05;
22
+ }
23
+
24
+ .statusContainerRow {
25
+ display: flex;
26
+ width: 100%;
27
+ border: none;
28
+ flex: 1;
29
+ flex-wrap: wrap;
30
+ gap: layout.$spacing-03;
31
+ justify-content: flex-start;
32
+ }
@@ -0,0 +1,45 @@
1
+ import { formatDate, parseDate } from '@openmrs/esm-framework';
2
+ import React from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import styles from './stock-operation-status.scss';
5
+
6
+ type Props = {
7
+ status: string;
8
+ statusFilledDate: string;
9
+ statusFillerGivenName?: string;
10
+ statusFillerFamilyName?: string;
11
+ extraStatusinfo?: React.ReactNode;
12
+ };
13
+
14
+ const StockOpertationStatus: React.FC<Props> = ({
15
+ status,
16
+ statusFillerFamilyName,
17
+ statusFillerGivenName,
18
+ statusFilledDate,
19
+ extraStatusinfo,
20
+ }) => {
21
+ const { t } = useTranslation();
22
+ return (
23
+ <div>
24
+ <span className={styles.textHeading}>{status}:</span>
25
+ <div className={styles.statusDescriptions}>
26
+ <span className={styles.text}>
27
+ {formatDate(parseDate(statusFilledDate), {
28
+ time: true,
29
+ mode: 'standard',
30
+ })}
31
+ </span>
32
+
33
+ <span className={styles.text}>{t('by', 'By')}</span>
34
+
35
+ <span className={styles.text}>
36
+ {statusFillerFamilyName} &nbsp;
37
+ {statusFillerGivenName}
38
+ </span>
39
+ {extraStatusinfo}
40
+ </div>
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export default StockOpertationStatus;
@@ -1,39 +1,40 @@
1
- import React, { useEffect, useMemo } from 'react';
2
1
  import { ButtonSkeleton, OverflowMenu, OverflowMenuItem } from '@carbon/react';
3
2
  import { OverflowMenuVertical } from '@carbon/react/icons';
4
- import { useStockOperationTypes, useUserRoles } from '../../stock-lookups/stock-lookups.resource';
5
- import { StockOperationType } from '../../core/api/types/stockOperation/StockOperationType';
3
+ import { showSnackbar } from '@openmrs/esm-framework';
4
+ import React, { useCallback, useEffect } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { OperationType, StockOperationType } from '../../core/api/types/stockOperation/StockOperationType';
7
+ import { launchStockoperationAddOrEditDialog } from '../stock-operation.utils';
8
+ import useFilteredOperationTypesByRoles from '../stock-operations-forms/hooks/useFilteredOperationTypesByRoles';
6
9
 
7
- interface StockOperationTypesSelectorProps {
8
- onOperationTypeSelected?: (operation: StockOperationType) => void;
9
- onOperationLoaded?: (operation: StockOperationType[]) => void;
10
- }
10
+ const StockOperationTypesSelector = () => {
11
+ const { t } = useTranslation();
12
+ const { error, isLoading, operationTypes } = useFilteredOperationTypesByRoles();
11
13
 
12
- const StockOperationTypesSelector: React.FC<StockOperationTypesSelectorProps> = ({
13
- onOperationTypeSelected,
14
- onOperationLoaded,
15
- }) => {
16
- const {
17
- types: { results: createOperationTypes },
18
- isLoading,
19
- error,
20
- } = useStockOperationTypes();
21
- const { userRoles } = useUserRoles();
14
+ const handleSelect = useCallback(
15
+ (stockOperationType: StockOperationType) => {
16
+ const isStockIssueOperation = stockOperationType.operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE;
22
17
 
23
- const filterOperationTypes = useMemo(() => {
24
- const applicablePrivilegeScopes = userRoles?.operationTypes?.map((p) => p.operationTypeUuid) || [];
25
- const uniqueApplicablePrivilegeScopes = [...new Set(applicablePrivilegeScopes)];
26
-
27
- return createOperationTypes?.filter((p) => uniqueApplicablePrivilegeScopes.includes(p.uuid)) || [];
28
- }, [createOperationTypes, userRoles]);
18
+ launchStockoperationAddOrEditDialog(t, stockOperationType, undefined);
19
+ },
20
+ [t],
21
+ );
29
22
 
30
23
  useEffect(() => {
31
- onOperationLoaded?.(filterOperationTypes);
32
- }, [filterOperationTypes, onOperationLoaded]);
24
+ if (error) {
25
+ showSnackbar({
26
+ kind: 'error',
27
+ title: t('stockOperationError', 'Error loading stock operation types'),
28
+ subtitle: error?.message,
29
+ });
30
+ }
31
+ }, [error, t]);
32
+
33
+ if (isLoading) return <ButtonSkeleton />;
33
34
 
34
- if (isLoading || error) return <ButtonSkeleton />;
35
+ if (error) return null;
35
36
 
36
- return filterOperationTypes && filterOperationTypes.length ? (
37
+ return operationTypes && operationTypes.length ? (
37
38
  <OverflowMenu
38
39
  renderIcon={() => (
39
40
  <>
@@ -53,14 +54,14 @@ const StockOperationTypesSelector: React.FC<StockOperationTypesSelectorProps> =
53
54
  whiteSpace: 'nowrap',
54
55
  }}
55
56
  >
56
- {filterOperationTypes
57
+ {operationTypes
57
58
  .sort((a, b) => a.name.localeCompare(b.name))
58
59
  .map((operation) => (
59
60
  <OverflowMenuItem
60
61
  key={operation.uuid}
61
62
  itemText={operation.name}
62
63
  onClick={() => {
63
- onOperationTypeSelected?.(operation);
64
+ handleSelect(operation);
64
65
  }}
65
66
  />
66
67
  ))}
@@ -1,93 +1,30 @@
1
+ import { showModal } from '@openmrs/esm-framework';
1
2
  import React from 'react';
2
- import { closeOverlay, launchOverlay } from '../core/components/overlay/hook';
3
- import { FetchResponse, restBaseUrl, showModal, showSnackbar } from '@openmrs/esm-framework';
4
3
  import { TFunction } from 'react-i18next';
5
- import { StockOperationDTO } from '../core/api/types/stockOperation/StockOperationDTO';
6
- import { createStockOperation, updateStockOperation } from './stock-operations.resource';
7
- import AddStockOperation from './add-stock-operation/add-stock-operation.component';
8
- import { OperationType, StockOperationType } from '../core/api/types/stockOperation/StockOperationType';
9
4
  import { useLocation } from 'react-router-dom';
10
- import { extractErrorMessagesFromResponse } from '../constants';
11
- import { handleMutate } from '../utils';
12
-
13
- export const addOrEditStockOperation = async (
14
- t: TFunction,
15
- stockOperation: StockOperationDTO,
16
- isEditing: boolean,
17
- operation?: StockOperationType,
18
- ) => {
19
- const payload = stockOperation;
20
- try {
21
- if (operation.operationType === 'requisition') {
22
- delete payload.destinationName;
23
- }
24
- if (operation.operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE) {
25
- const stockIssueOpsTypeUuid = '66666666-6666-6666-6666-666666666666';
26
- delete payload.completedDate;
27
- delete payload.completedBy;
28
- delete payload.completedByFamilyName;
29
- delete payload.completedByGivenName;
30
- delete payload.operationTypeUuid;
31
- delete payload.permission;
32
- delete payload.locked;
33
-
34
- payload['operationTypeUuid'] = stockIssueOpsTypeUuid;
35
- }
36
- const response: FetchResponse<StockOperationDTO> = await (isEditing ? updateStockOperation : createStockOperation)(
37
- payload,
38
- );
39
-
40
- if (response?.data) {
41
- handleMutate(`${restBaseUrl}/stockmanagement/stockoperation`);
42
- showSnackbar({
43
- isLowContrast: true,
44
- title: isEditing
45
- ? t('editStockOperation', 'Edit stock operation')
46
- : t('addStockOperation', 'Add stock operation'),
47
- kind: 'success',
48
- subtitle: isEditing
49
- ? t('stockOperationEdited', 'Stock operation edited successfully')
50
- : t('stockOperationAdded', 'Stock operation added successfully'),
51
- });
52
-
53
- closeOverlay();
54
- }
55
- } catch (error) {
56
- const errorMessages = extractErrorMessagesFromResponse(error);
57
- showSnackbar({
58
- subtitle: errorMessages.join(', '),
59
- title: t('errorSavingForm', 'Error on saving form'),
60
- kind: 'error',
61
- isLowContrast: true,
62
- });
63
- }
64
- };
5
+ import { StockOperationDTO } from '../core/api/types/stockOperation/StockOperationDTO';
6
+ import { StockOperationType } from '../core/api/types/stockOperation/StockOperationType';
7
+ import { launchOverlay } from '../core/components/overlay/hook';
8
+ import StockOperationForm from './stock-operations-forms/stock-operation-form.component';
65
9
 
66
- export const launchAddOrEditDialog = (
10
+ export const launchStockoperationAddOrEditDialog = (
67
11
  t: TFunction,
68
- stockOperation: StockOperationDTO,
69
- isEditing: boolean,
70
- operation?: StockOperationType,
71
- operations?: StockOperationType[],
72
- canPrint?: boolean,
12
+ operationType: StockOperationType,
13
+ stockOperation?: StockOperationDTO,
14
+ stockRequisitionUuid?: string, // Only suplied on stock issue (when overlay is launched for stock issue)
73
15
  ) => {
74
- const printEnabled = canPrint !== undefined ? canPrint : stockOperation?.status === 'COMPLETED';
75
-
76
16
  launchOverlay(
77
- isEditing
17
+ stockOperation
78
18
  ? t('editOperationTitle', 'Edit {{operationType}}', {
79
19
  operationType: stockOperation?.operationTypeName,
80
20
  })
81
21
  : t('newOperationTitle', 'New: {{operationName}}', {
82
- operationName: operation?.name,
22
+ operationName: operationType?.name,
83
23
  }),
84
- <AddStockOperation
85
- model={stockOperation}
86
- onSave={(stockOperation) => addOrEditStockOperation(t, stockOperation, isEditing, operation)}
87
- isEditing={isEditing}
88
- operation={operation}
89
- canEdit={isEditing ? (stockOperation?.status === 'NEW' ? true : false) : true}
90
- canPrint={printEnabled}
24
+ <StockOperationForm
25
+ stockOperationType={operationType}
26
+ stockOperation={stockOperation}
27
+ stockRequisitionUuid={stockRequisitionUuid}
91
28
  />,
92
29
  );
93
30
  };
@@ -100,7 +37,7 @@ export function getStockOperationUniqueId() {
100
37
  return `${new Date().getTime()}-${Math.random().toString(36).substring(2, 16)}`;
101
38
  }
102
39
 
103
- export const showActionDialogButton = async (title: string, requireReason: boolean, operation: StockOperationDTO) => {
40
+ export const showActionDialogButton = (title: string, requireReason: boolean, operation: StockOperationDTO) => {
104
41
  const dispose = showModal('stock-operation-dialog', {
105
42
  title: title,
106
43
  operation: operation,
@@ -1,60 +1,48 @@
1
- import React from 'react';
1
+ import React, { useEffect, useMemo } from 'react';
2
2
 
3
- import { Button } from '@carbon/react';
4
- import { useTranslation } from 'react-i18next';
3
+ import { Button, InlineLoading } from '@carbon/react';
5
4
  import { DeliveryTruck } from '@carbon/react/icons';
5
+ import { useTranslation } from 'react-i18next';
6
6
  import { StockOperationDTO } from '../../core/api/types/stockOperation/StockOperationDTO';
7
- import { StockOperationType } from '../../core/api/types/stockOperation/StockOperationType';
8
- import { launchAddOrEditDialog } from '../stock-operation.utils';
7
+ import { OperationType } from '../../core/api/types/stockOperation/StockOperationType';
8
+ import { useStockOperationTypes } from '../../stock-lookups/stock-lookups.resource';
9
+ import { launchStockoperationAddOrEditDialog } from '../stock-operation.utils';
10
+ import { showSnackbar } from '@openmrs/esm-framework';
9
11
 
10
12
  interface StockOperationIssueStockButtonProps {
11
13
  operation: StockOperationDTO;
12
- operations: StockOperationType[];
13
14
  }
14
15
 
15
- const StockOperationIssueStockButton: React.FC<StockOperationIssueStockButtonProps> = ({ operation, operations }) => {
16
+ const StockOperationIssueStockButton: React.FC<StockOperationIssueStockButtonProps> = ({ operation }) => {
16
17
  const { t } = useTranslation();
17
- const type: StockOperationType = {
18
- uuid: '',
19
- name: 'Stock Issue',
20
- description: '',
21
- operationType: 'stockissue',
22
- hasSource: false,
23
- sourceType: 'Location',
24
- hasDestination: false,
25
- destinationType: 'Location',
26
- hasRecipient: false,
27
- recipientRequired: false,
28
- availableWhenReserved: false,
29
- allowExpiredBatchNumbers: false,
30
- stockOperationTypeLocationScopes: [],
31
- creator: undefined,
32
- dateCreated: undefined,
33
- changedBy: undefined,
34
- dateChanged: undefined,
35
- dateVoided: undefined,
36
- voidedBy: undefined,
37
- voidReason: '',
38
- voided: false,
39
- };
18
+ const { error, isLoading, types } = useStockOperationTypes();
19
+ const stockIssueOperationType = useMemo(
20
+ () => types?.results?.find((type) => type.operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE),
21
+ [types],
22
+ );
40
23
 
41
- const modifiedOperation = addRequisitionStockOperation(operation);
42
24
  const handleButtonClick = () => {
43
- launchAddOrEditDialog(t, modifiedOperation, false, type, operations, false);
25
+ launchStockoperationAddOrEditDialog(t, stockIssueOperationType, undefined, operation.uuid);
44
26
  };
45
27
 
28
+ useEffect(() => {
29
+ if (error) {
30
+ showSnackbar({
31
+ kind: 'error',
32
+ title: t('stockOperationError', 'Error loading stock operation types'),
33
+ subtitle: error?.message,
34
+ });
35
+ }
36
+ }, [error, t]);
37
+
38
+ if (isLoading)
39
+ return <InlineLoading description="" iconDescription={t('loadingOperationTypes', 'Loading operation types')} />;
40
+
46
41
  return (
47
42
  <Button onClick={handleButtonClick} kind="tertiary" renderIcon={(props) => <DeliveryTruck size={16} {...props} />}>
48
43
  {t('issueStock', 'Issue Stock ')}
49
44
  </Button>
50
45
  );
51
46
  };
52
- function addRequisitionStockOperation(stockOperation) {
53
- const { uuid } = stockOperation;
54
- return {
55
- ...stockOperation,
56
- requisitionStockOperationUuid: uuid,
57
- };
58
- }
59
47
 
60
48
  export default StockOperationIssueStockButton;