@openmrs/esm-stock-management-app 1.0.1-pre.783 → 1.0.1-pre.788

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 (128) 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/922.js +1 -0
  13. package/dist/922.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 +75 -51
  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/config-schema.ts +6 -0
  22. package/src/core/utils/utils.ts +29 -0
  23. package/src/index.ts +4 -0
  24. package/src/routes.json +9 -0
  25. package/src/stock-items/add-stock-item/transactions/printout/transactions-stockcard-printout.component.tsx +8 -12
  26. package/src/stock-items/add-stock-item/transactions/transactions.component.tsx +8 -12
  27. package/src/stock-items/stock-items.resource.ts +5 -5
  28. package/src/stock-lookups/stock-lookups.resource.ts +2 -2
  29. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.scss +34 -0
  30. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.tsx +111 -0
  31. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.component.tsx +87 -0
  32. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.scss +31 -0
  33. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operations-status.tsx +45 -0
  34. package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx +41 -16
  35. package/src/stock-operations/stock-operation-reference.component.tsx +64 -0
  36. package/src/stock-operations/stock-operation-status/stock-operation-status-row.tsx +77 -0
  37. package/src/stock-operations/stock-operation-status/stock-operation-status.scss +32 -0
  38. package/src/stock-operations/stock-operation-status/stock-operation-status.tsx +45 -0
  39. package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +30 -29
  40. package/src/stock-operations/stock-operation.utils.tsx +16 -79
  41. package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +27 -39
  42. package/src/stock-operations/stock-operations-dialog/stock-operations-print-button.component.tsx +51 -59
  43. package/src/stock-operations/{stock-item-selector/stock-item-selector.resource.tsx → stock-operations-forms/hooks/useFilterableStockItems.ts} +4 -4
  44. package/src/stock-operations/stock-operations-forms/hooks/useFilteredOperationTypesByRoles.ts +30 -0
  45. package/src/stock-operations/stock-operations-forms/hooks/useOperationTypePermisions.ts +29 -0
  46. package/src/stock-operations/stock-operations-forms/hooks/useParties.ts +73 -0
  47. package/src/stock-operations/{users-selector/users-selector.resource.tsx → stock-operations-forms/hooks/useSearchUser.ts} +9 -7
  48. package/src/stock-operations/{batch-no-selector/batch-no-selector.resource.tsx → stock-operations-forms/hooks/useStockItemBatchNumbers.ts} +3 -3
  49. package/src/stock-operations/stock-operations-forms/hooks/useStockOperationLinks.ts +20 -0
  50. package/src/stock-operations/stock-operations-forms/input-components/batch-no-selector.component.tsx +72 -0
  51. package/src/stock-operations/stock-operations-forms/input-components/batch-no-selector.test.tsx +90 -0
  52. 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
  53. package/src/stock-operations/stock-operations-forms/input-components/qty-uim-selector.test.tsx +157 -0
  54. package/src/stock-operations/stock-operations-forms/input-components/quantity-uom-selector.component.tsx +53 -0
  55. package/src/stock-operations/stock-operations-forms/input-components/stock-item-search.component.tsx +79 -0
  56. package/src/stock-operations/stock-operations-forms/input-components/stock-operation-reason-selector.component.tsx +59 -0
  57. package/src/stock-operations/stock-operations-forms/input-components/stock-operation-reason-selector.test.tsx +216 -0
  58. package/src/stock-operations/{batch-no-selector → stock-operations-forms/input-components}/unique-batch-no-entry-input.component.tsx +12 -7
  59. package/src/stock-operations/stock-operations-forms/input-components/user-selector.test.tsx +110 -0
  60. package/src/stock-operations/stock-operations-forms/input-components/users-selector.component.tsx +111 -0
  61. package/src/stock-operations/stock-operations-forms/step1.test.tsx +303 -0
  62. package/src/stock-operations/stock-operations-forms/step2.test.tsx +254 -0
  63. package/src/stock-operations/stock-operations-forms/step3.test.tsx +223 -0
  64. package/src/stock-operations/stock-operations-forms/steps/base-operation-details-form-step.tsx +241 -0
  65. package/src/stock-operations/stock-operations-forms/steps/quantity-uom-cell.component.tsx +33 -0
  66. package/src/stock-operations/stock-operations-forms/steps/received-items.component.tsx +110 -0
  67. package/src/stock-operations/stock-operations-forms/steps/stock-availability-cell.component.tsx +51 -0
  68. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-batch-no-cell.component.tsx +40 -0
  69. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-cell.component.tsx +50 -0
  70. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-expiry-cell.component.tsx +41 -0
  71. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.component.tsx +281 -0
  72. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.scc.scss +64 -0
  73. package/src/stock-operations/stock-operations-forms/steps/stock-operation-submission-form-step.component.tsx +243 -0
  74. package/src/stock-operations/stock-operations-forms/stock-issue-form-initializer-with-related-requisition-operation.component.tsx +55 -0
  75. package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.scss +41 -0
  76. package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.workspace.tsx +211 -0
  77. package/src/stock-operations/stock-operations-forms/stock-operation-form-header.component.tsx +166 -0
  78. package/src/stock-operations/stock-operations-forms/stock-operation-form.component.tsx +205 -0
  79. package/src/stock-operations/stock-operations-forms/stock-operation-form.scss +111 -0
  80. package/src/stock-operations/stock-operations-forms/stock-operation-related-link.component.tsx +45 -0
  81. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stepper.scss +41 -0
  82. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stock-operation-stepper.component.tsx +52 -0
  83. package/src/stock-operations/stock-operations-forms/stock-operations-form-utils.ts +32 -0
  84. package/src/stock-operations/stock-operations-table.component.tsx +57 -92
  85. package/src/stock-operations/stock-operations.resource.ts +16 -13
  86. package/src/stock-operations/validation-schema.ts +72 -14
  87. package/dist/766.js +0 -2
  88. package/dist/766.js.map +0 -1
  89. package/dist/822.js +0 -1
  90. package/dist/822.js.map +0 -1
  91. package/src/stock-operations/add-stock-operation/add-stock-operation.component.tsx +0 -349
  92. package/src/stock-operations/add-stock-operation/add-stock-operation.resource.tsx +0 -27
  93. package/src/stock-operations/add-stock-operation/add-stock-operation.scss +0 -60
  94. package/src/stock-operations/add-stock-operation/add-stock-operation.test.tsx +0 -192
  95. package/src/stock-operations/add-stock-operation/add-stock-operation.utils.tsx +0 -152
  96. package/src/stock-operations/add-stock-operation/add-stock-utils.ts +0 -103
  97. package/src/stock-operations/add-stock-operation/base-operation-details.component.tsx +0 -439
  98. package/src/stock-operations/add-stock-operation/base-operation-details.scss +0 -30
  99. package/src/stock-operations/add-stock-operation/received-items.component.tsx +0 -93
  100. package/src/stock-operations/add-stock-operation/stock-item-search/stock-item-search.component.tsx +0 -70
  101. package/src/stock-operations/add-stock-operation/stock-items-addition-row.component.tsx +0 -357
  102. package/src/stock-operations/add-stock-operation/stock-items-addition-row.resource.tsx +0 -0
  103. package/src/stock-operations/add-stock-operation/stock-items-addition-row.scss +0 -12
  104. package/src/stock-operations/add-stock-operation/stock-items-addition-row.test.tsx +0 -10
  105. package/src/stock-operations/add-stock-operation/stock-items-addition.component.scss +0 -17
  106. package/src/stock-operations/add-stock-operation/stock-items-addition.component.tsx +0 -254
  107. package/src/stock-operations/add-stock-operation/stock-operation-context/useStockOperationContext.tsx +0 -16
  108. package/src/stock-operations/add-stock-operation/stock-operation-reference.component.tsx +0 -39
  109. package/src/stock-operations/add-stock-operation/stock-operation-related-link.component.tsx +0 -38
  110. package/src/stock-operations/add-stock-operation/stock-operation-status.component.tsx +0 -170
  111. package/src/stock-operations/add-stock-operation/stock-operation-submission.component.tsx +0 -189
  112. package/src/stock-operations/add-stock-operation/stock-operation-submission.test.tsx +0 -138
  113. package/src/stock-operations/add-stock-operation/types.ts +0 -55
  114. package/src/stock-operations/add-stock-operation/validationSchema.ts +0 -54
  115. package/src/stock-operations/batch-no-selector/batch-no-selector.component.tsx +0 -114
  116. package/src/stock-operations/batch-no-selector/batch-no-selector.scss +0 -0
  117. package/src/stock-operations/batch-no-selector/batch-no-selector.test.tsx +0 -101
  118. package/src/stock-operations/party-selector/party-selector.component.tsx +0 -59
  119. package/src/stock-operations/qty-uom-selector/qty-uom-selector.component.tsx +0 -65
  120. package/src/stock-operations/qty-uom-selector/qty-uom-selector.resource.tsx +0 -0
  121. package/src/stock-operations/qty-uom-selector/qty-uom-selector.scss +0 -0
  122. package/src/stock-operations/qty-uom-selector/qty-uom-selector.test.tsx +0 -10
  123. package/src/stock-operations/stock-item-selector/stock-item-selector.component.tsx +0 -69
  124. package/src/stock-operations/stock-item-selector/stock-item-selector.scss +0 -0
  125. package/src/stock-operations/stock-item-selector/stock-item-selector.test.tsx +0 -10
  126. package/src/stock-operations/stock-operation-reason-selector/stock-operation-reason-selector.component.tsx +0 -62
  127. package/src/stock-operations/users-selector/users-selector.component.tsx +0 -75
  128. /package/dist/{766.js.LICENSE.txt → 493.js.LICENSE.txt} +0 -0
@@ -0,0 +1,111 @@
1
+ import {
2
+ DataTable,
3
+ Pagination,
4
+ Search,
5
+ Table,
6
+ TableBody,
7
+ TableCell,
8
+ TableHead,
9
+ TableHeader,
10
+ TableRow,
11
+ Tile,
12
+ } from '@carbon/react';
13
+ import { formatDate, parseDate, usePagination } from '@openmrs/esm-framework';
14
+ import React, { useMemo, useState } from 'react';
15
+ import { useTranslation } from 'react-i18next';
16
+ import { StockOperationItemDTO } from '../../../core/api/types/stockOperation/StockOperationItemDTO';
17
+ import styles from './stock-items-table.scss';
18
+
19
+ type Props = {
20
+ items: Array<StockOperationItemDTO>;
21
+ };
22
+ const StockItemsTable: React.FC<Props> = ({ items }) => {
23
+ const { t } = useTranslation();
24
+ const [pageSize, setPageSize] = useState(10);
25
+ const pageSizesOptions = useMemo(() => [5, 10, 20, 50, 100], []);
26
+ const [searchText, setSearchText] = useState();
27
+
28
+ const handleSearch = (item: StockOperationItemDTO) => {
29
+ if (!searchText) return true;
30
+ return item.commonName.toLowerCase().includes(searchText);
31
+ };
32
+ const filtered = items.filter(handleSearch);
33
+ const { results, totalPages, currentPage, goTo } = usePagination(filtered, pageSize);
34
+
35
+ const headers = useMemo(
36
+ () => [
37
+ {
38
+ header: t('item', 'Item'),
39
+ key: 'commonName',
40
+ },
41
+ {
42
+ header: t('batchNo', 'Batch No'),
43
+ key: 'batchNo',
44
+ },
45
+ {
46
+ header: t('expiry', 'Expiry'),
47
+ key: 'expiration',
48
+ },
49
+ {
50
+ header: t('qty', 'Qty'),
51
+ key: 'quantity',
52
+ },
53
+ {
54
+ header: t('uom', 'UoM'),
55
+ key: 'stockItemPackagingUOMName',
56
+ },
57
+ ],
58
+ [t],
59
+ );
60
+
61
+ const tableRows = useMemo(
62
+ () =>
63
+ results.map((item, index) => ({
64
+ id: index,
65
+ ...item,
66
+ expiration: item.expiration ? formatDate(parseDate(`${item.expiration}`)) : '--',
67
+ })),
68
+ [results],
69
+ );
70
+
71
+ return (
72
+ <Tile className={styles.container}>
73
+ <span className={styles.title}>{t('stockItems', 'Stock items')}</span>
74
+ <Search value={searchText} onChange={({ target: { value } }) => setSearchText(value)} />
75
+ <DataTable useZebraStyles={true} rows={tableRows} headers={headers}>
76
+ {({ rows, headers, getTableProps, getHeaderProps, getRowProps }) => (
77
+ <Table {...getTableProps()}>
78
+ <TableHead>
79
+ <TableRow>
80
+ {headers.map((header) => (
81
+ <TableHeader {...getHeaderProps({ header })}>{header.header}</TableHeader>
82
+ ))}
83
+ </TableRow>
84
+ </TableHead>
85
+ <TableBody>
86
+ {rows.map((row) => (
87
+ <TableRow {...getRowProps({ row })}>
88
+ {row.cells.map((cell) => (
89
+ <TableCell key={cell.id}>{cell.value}</TableCell>
90
+ ))}
91
+ </TableRow>
92
+ ))}
93
+ </TableBody>
94
+ </Table>
95
+ )}
96
+ </DataTable>
97
+ <Pagination
98
+ page={currentPage}
99
+ pageSize={pageSize}
100
+ pageSizes={pageSizesOptions}
101
+ totalItems={filtered.length}
102
+ onChange={({ page, pageSize }) => {
103
+ goTo(page);
104
+ setPageSize(pageSize);
105
+ }}
106
+ />
107
+ </Tile>
108
+ );
109
+ };
110
+
111
+ export default StockItemsTable;
@@ -0,0 +1,87 @@
1
+ import { Layer, Row } from '@carbon/react';
2
+ import React from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { StockOperationDTO } from '../../../core/api/types/stockOperation/StockOperationDTO';
5
+ import styles from './stock-operation-expanded-row.scss';
6
+ import StockItemsTable from './stock-items-table';
7
+ import StockOpertationStatus from './stock-operations-status';
8
+
9
+ interface StockOperationExpandedRowProps {
10
+ model: StockOperationDTO;
11
+ }
12
+
13
+ const StockOperationExpandedRow: React.FC<StockOperationExpandedRowProps> = (props) => {
14
+ const { t } = useTranslation();
15
+ return (
16
+ <>
17
+ <Layer className={styles.statusContainer}>
18
+ <Row className={styles.statusContainerRow}>
19
+ {props.model?.dateCreated && (
20
+ <StockOpertationStatus
21
+ status={t('started', 'Started')}
22
+ statusFilledDate={props.model?.dateCreated.toString()}
23
+ statusFillerFamilyName={props.model?.creatorFamilyName}
24
+ statusFillerGivenName={props.model?.creatorGivenName}
25
+ />
26
+ )}
27
+ {props.model.submittedDate && (
28
+ <StockOpertationStatus
29
+ status={t('submitted', 'Submitted')}
30
+ statusFilledDate={props.model?.submittedDate.toString()}
31
+ statusFillerFamilyName={props.model?.submittedByFamilyName}
32
+ statusFillerGivenName={props.model?.submittedByGivenName}
33
+ />
34
+ )}
35
+ {props.model?.dispatchedDate && (
36
+ <StockOpertationStatus
37
+ status={t('dispatched', 'Dispatched')}
38
+ statusFilledDate={props.model?.dispatchedDate.toString()}
39
+ statusFillerFamilyName={props.model?.dispatchedByFamilyName}
40
+ statusFillerGivenName={props.model?.dispatchedByGivenName}
41
+ />
42
+ )}
43
+ {props.model?.returnedDate && (
44
+ <StockOpertationStatus
45
+ status={t('returned', 'Returned')}
46
+ statusFilledDate={props.model?.returnedDate.toString()}
47
+ statusFillerFamilyName={props.model?.returnedByFamilyName}
48
+ statusFillerGivenName={props.model?.returnedByGivenName}
49
+ extraStatusinfo={<span className={styles.text}>{props.model?.returnReason}</span>}
50
+ />
51
+ )}
52
+ {props.model?.completedDate && (
53
+ <StockOpertationStatus
54
+ status={t('completed', 'Completed')}
55
+ statusFilledDate={props.model?.completedDate.toString()}
56
+ statusFillerFamilyName={props.model?.completedByFamilyName}
57
+ statusFillerGivenName={props.model?.completedByGivenName}
58
+ />
59
+ )}
60
+ {props.model?.status === 'CANCELLED' && (
61
+ <StockOpertationStatus
62
+ status={t('cancelled', 'Cancelled')}
63
+ statusFilledDate={props.model?.cancelledDate.toString()}
64
+ statusFillerFamilyName={props.model?.cancelledByFamilyName}
65
+ statusFillerGivenName={props.model?.cancelledByGivenName}
66
+ extraStatusinfo={<span className={styles.text}>{props.model?.cancelReason}</span>}
67
+ />
68
+ )}
69
+ {props.model?.status === 'REJECTED' && (
70
+ <StockOpertationStatus
71
+ status={t('rejected', 'Rejected')}
72
+ statusFilledDate={props.model?.rejectedDate.toString()}
73
+ statusFillerFamilyName={props.model?.rejectedByFamilyName}
74
+ statusFillerGivenName={props.model?.rejectedByGivenName}
75
+ extraStatusinfo={<span>{props.model?.rejectionReason}</span>}
76
+ />
77
+ )}
78
+ </Row>
79
+ <Row className={styles.statusContainerRow}>
80
+ <StockItemsTable items={props.model.stockOperationItems} />
81
+ </Row>
82
+ </Layer>
83
+ </>
84
+ );
85
+ };
86
+
87
+ export default StockOperationExpandedRow;
@@ -0,0 +1,31 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '~@openmrs/esm-styleguide/src/vars' as *;
4
+
5
+ .textHeading {
6
+ font-weight: bold;
7
+ }
8
+
9
+ .statusDescriptions {
10
+ margin-top: 4px;
11
+
12
+ .text {
13
+ margin-right: 4px;
14
+ }
15
+ }
16
+
17
+ .statusContainer {
18
+ display: flex;
19
+ margin: 10px;
20
+ gap: layout.$spacing-05;
21
+ flex-direction: column;
22
+ padding: layout.$spacing-05;
23
+ }
24
+
25
+ .statusContainerRow {
26
+ display: flex;
27
+ width: 100%;
28
+ border: none;
29
+ gap: layout.$spacing-05;
30
+ flex: 1;
31
+ }
@@ -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-expanded-row.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,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
  };
@@ -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
  ))}