@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.
- package/__mocks__/index.ts +1 -0
- package/__mocks__/operation-type.mock.ts +532 -0
- package/dist/155.js +1 -0
- package/dist/155.js.map +1 -0
- package/dist/172.js +1 -1
- package/dist/20.js +1 -1
- package/dist/290.js +1 -1
- package/dist/493.js +2 -0
- package/dist/493.js.map +1 -0
- package/dist/606.js +1 -1
- package/dist/627.js +1 -1
- package/dist/922.js +1 -0
- package/dist/922.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-stock-management-app.js +1 -1
- package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +75 -51
- package/dist/openmrs-esm-stock-management-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/config-schema.ts +6 -0
- package/src/core/utils/utils.ts +29 -0
- package/src/index.ts +4 -0
- package/src/routes.json +9 -0
- package/src/stock-items/add-stock-item/transactions/printout/transactions-stockcard-printout.component.tsx +8 -12
- package/src/stock-items/add-stock-item/transactions/transactions.component.tsx +8 -12
- package/src/stock-items/stock-items.resource.ts +5 -5
- package/src/stock-lookups/stock-lookups.resource.ts +2 -2
- package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.scss +34 -0
- package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.tsx +111 -0
- package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.component.tsx +87 -0
- package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.scss +31 -0
- package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operations-status.tsx +45 -0
- package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx +41 -16
- package/src/stock-operations/stock-operation-reference.component.tsx +64 -0
- package/src/stock-operations/stock-operation-status/stock-operation-status-row.tsx +77 -0
- package/src/stock-operations/stock-operation-status/stock-operation-status.scss +32 -0
- package/src/stock-operations/stock-operation-status/stock-operation-status.tsx +45 -0
- package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +30 -29
- package/src/stock-operations/stock-operation.utils.tsx +16 -79
- package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +27 -39
- package/src/stock-operations/stock-operations-dialog/stock-operations-print-button.component.tsx +51 -59
- package/src/stock-operations/{stock-item-selector/stock-item-selector.resource.tsx → stock-operations-forms/hooks/useFilterableStockItems.ts} +4 -4
- package/src/stock-operations/stock-operations-forms/hooks/useFilteredOperationTypesByRoles.ts +30 -0
- package/src/stock-operations/stock-operations-forms/hooks/useOperationTypePermisions.ts +29 -0
- package/src/stock-operations/stock-operations-forms/hooks/useParties.ts +73 -0
- package/src/stock-operations/{users-selector/users-selector.resource.tsx → stock-operations-forms/hooks/useSearchUser.ts} +9 -7
- package/src/stock-operations/{batch-no-selector/batch-no-selector.resource.tsx → stock-operations-forms/hooks/useStockItemBatchNumbers.ts} +3 -3
- package/src/stock-operations/stock-operations-forms/hooks/useStockOperationLinks.ts +20 -0
- package/src/stock-operations/stock-operations-forms/input-components/batch-no-selector.component.tsx +72 -0
- package/src/stock-operations/stock-operations-forms/input-components/batch-no-selector.test.tsx +90 -0
- 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
- package/src/stock-operations/stock-operations-forms/input-components/qty-uim-selector.test.tsx +157 -0
- package/src/stock-operations/stock-operations-forms/input-components/quantity-uom-selector.component.tsx +53 -0
- package/src/stock-operations/stock-operations-forms/input-components/stock-item-search.component.tsx +79 -0
- package/src/stock-operations/stock-operations-forms/input-components/stock-operation-reason-selector.component.tsx +59 -0
- package/src/stock-operations/stock-operations-forms/input-components/stock-operation-reason-selector.test.tsx +216 -0
- package/src/stock-operations/{batch-no-selector → stock-operations-forms/input-components}/unique-batch-no-entry-input.component.tsx +12 -7
- package/src/stock-operations/stock-operations-forms/input-components/user-selector.test.tsx +110 -0
- package/src/stock-operations/stock-operations-forms/input-components/users-selector.component.tsx +111 -0
- package/src/stock-operations/stock-operations-forms/step1.test.tsx +303 -0
- package/src/stock-operations/stock-operations-forms/step2.test.tsx +254 -0
- package/src/stock-operations/stock-operations-forms/step3.test.tsx +223 -0
- package/src/stock-operations/stock-operations-forms/steps/base-operation-details-form-step.tsx +241 -0
- package/src/stock-operations/stock-operations-forms/steps/quantity-uom-cell.component.tsx +33 -0
- package/src/stock-operations/stock-operations-forms/steps/received-items.component.tsx +110 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-availability-cell.component.tsx +51 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-batch-no-cell.component.tsx +40 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-cell.component.tsx +50 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-expiry-cell.component.tsx +41 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.component.tsx +281 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.scc.scss +64 -0
- package/src/stock-operations/stock-operations-forms/steps/stock-operation-submission-form-step.component.tsx +243 -0
- package/src/stock-operations/stock-operations-forms/stock-issue-form-initializer-with-related-requisition-operation.component.tsx +55 -0
- package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.scss +41 -0
- package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.workspace.tsx +211 -0
- package/src/stock-operations/stock-operations-forms/stock-operation-form-header.component.tsx +166 -0
- package/src/stock-operations/stock-operations-forms/stock-operation-form.component.tsx +205 -0
- package/src/stock-operations/stock-operations-forms/stock-operation-form.scss +111 -0
- package/src/stock-operations/stock-operations-forms/stock-operation-related-link.component.tsx +45 -0
- package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stepper.scss +41 -0
- package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stock-operation-stepper.component.tsx +52 -0
- package/src/stock-operations/stock-operations-forms/stock-operations-form-utils.ts +32 -0
- package/src/stock-operations/stock-operations-table.component.tsx +57 -92
- package/src/stock-operations/stock-operations.resource.ts +16 -13
- package/src/stock-operations/validation-schema.ts +72 -14
- package/dist/766.js +0 -2
- package/dist/766.js.map +0 -1
- package/dist/822.js +0 -1
- package/dist/822.js.map +0 -1
- package/src/stock-operations/add-stock-operation/add-stock-operation.component.tsx +0 -349
- package/src/stock-operations/add-stock-operation/add-stock-operation.resource.tsx +0 -27
- package/src/stock-operations/add-stock-operation/add-stock-operation.scss +0 -60
- package/src/stock-operations/add-stock-operation/add-stock-operation.test.tsx +0 -192
- package/src/stock-operations/add-stock-operation/add-stock-operation.utils.tsx +0 -152
- package/src/stock-operations/add-stock-operation/add-stock-utils.ts +0 -103
- package/src/stock-operations/add-stock-operation/base-operation-details.component.tsx +0 -439
- package/src/stock-operations/add-stock-operation/base-operation-details.scss +0 -30
- package/src/stock-operations/add-stock-operation/received-items.component.tsx +0 -93
- package/src/stock-operations/add-stock-operation/stock-item-search/stock-item-search.component.tsx +0 -70
- package/src/stock-operations/add-stock-operation/stock-items-addition-row.component.tsx +0 -357
- package/src/stock-operations/add-stock-operation/stock-items-addition-row.resource.tsx +0 -0
- package/src/stock-operations/add-stock-operation/stock-items-addition-row.scss +0 -12
- package/src/stock-operations/add-stock-operation/stock-items-addition-row.test.tsx +0 -10
- package/src/stock-operations/add-stock-operation/stock-items-addition.component.scss +0 -17
- package/src/stock-operations/add-stock-operation/stock-items-addition.component.tsx +0 -254
- package/src/stock-operations/add-stock-operation/stock-operation-context/useStockOperationContext.tsx +0 -16
- package/src/stock-operations/add-stock-operation/stock-operation-reference.component.tsx +0 -39
- package/src/stock-operations/add-stock-operation/stock-operation-related-link.component.tsx +0 -38
- package/src/stock-operations/add-stock-operation/stock-operation-status.component.tsx +0 -170
- package/src/stock-operations/add-stock-operation/stock-operation-submission.component.tsx +0 -189
- package/src/stock-operations/add-stock-operation/stock-operation-submission.test.tsx +0 -138
- package/src/stock-operations/add-stock-operation/types.ts +0 -55
- package/src/stock-operations/add-stock-operation/validationSchema.ts +0 -54
- package/src/stock-operations/batch-no-selector/batch-no-selector.component.tsx +0 -114
- package/src/stock-operations/batch-no-selector/batch-no-selector.scss +0 -0
- package/src/stock-operations/batch-no-selector/batch-no-selector.test.tsx +0 -101
- package/src/stock-operations/party-selector/party-selector.component.tsx +0 -59
- package/src/stock-operations/qty-uom-selector/qty-uom-selector.component.tsx +0 -65
- package/src/stock-operations/qty-uom-selector/qty-uom-selector.resource.tsx +0 -0
- package/src/stock-operations/qty-uom-selector/qty-uom-selector.scss +0 -0
- package/src/stock-operations/qty-uom-selector/qty-uom-selector.test.tsx +0 -10
- package/src/stock-operations/stock-item-selector/stock-item-selector.component.tsx +0 -69
- package/src/stock-operations/stock-item-selector/stock-item-selector.scss +0 -0
- package/src/stock-operations/stock-item-selector/stock-item-selector.test.tsx +0 -10
- package/src/stock-operations/stock-operation-reason-selector/stock-operation-reason-selector.component.tsx +0 -62
- package/src/stock-operations/users-selector/users-selector.component.tsx +0 -75
- /package/dist/{766.js.LICENSE.txt → 493.js.LICENSE.txt} +0 -0
package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.tsx
ADDED
@@ -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}
|
37
|
+
{statusFillerGivenName}
|
38
|
+
</span>
|
39
|
+
{extraStatusinfo}
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
);
|
43
|
+
};
|
44
|
+
|
45
|
+
export default StockOpertationStatus;
|
package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx
CHANGED
@@ -1,33 +1,58 @@
|
|
1
|
-
import
|
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 {
|
7
|
-
import
|
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
|
-
|
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
|
-
|
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
|
-
|
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 &&
|
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}
|
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 {
|
5
|
-
import {
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
}
|
10
|
+
const StockOperationTypesSelector = () => {
|
11
|
+
const { t } = useTranslation();
|
12
|
+
const { error, isLoading, operationTypes } = useFilteredOperationTypesByRoles();
|
11
13
|
|
12
|
-
const
|
13
|
-
|
14
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
32
|
-
|
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 (
|
35
|
+
if (error) return null;
|
35
36
|
|
36
|
-
return
|
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
|
-
{
|
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
|
-
|
64
|
+
handleSelect(operation);
|
64
65
|
}}
|
65
66
|
/>
|
66
67
|
))}
|