@openmrs/esm-stock-management-app 3.0.1-pre.865 → 3.0.1-pre.868

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.
@@ -22,7 +22,7 @@
22
22
  "auxiliaryFiles": [
23
23
  "10.js.map"
24
24
  ],
25
- "hash": "17ed7dc17cd26a7c",
25
+ "hash": "f836cf8ad4ff0f4c",
26
26
  "childrenByOrder": {}
27
27
  },
28
28
  {
@@ -30,9 +30,9 @@
30
30
  "initial": false,
31
31
  "entry": false,
32
32
  "recorded": false,
33
- "size": 1236498,
33
+ "size": 1236590,
34
34
  "sizes": {
35
- "javascript": 1236330,
35
+ "javascript": 1236422,
36
36
  "consume-shared": 168
37
37
  },
38
38
  "names": [],
@@ -46,7 +46,7 @@
46
46
  "auxiliaryFiles": [
47
47
  "14.js.map"
48
48
  ],
49
- "hash": "d9d4b3c843b1cae5",
49
+ "hash": "19b4b932f121b45a",
50
50
  "childrenByOrder": {}
51
51
  },
52
52
  {
@@ -70,7 +70,7 @@
70
70
  "auxiliaryFiles": [
71
71
  "20.js.map"
72
72
  ],
73
- "hash": "93c6b6b454c03f48",
73
+ "hash": "367205a6f567b46f",
74
74
  "childrenByOrder": {}
75
75
  },
76
76
  {
@@ -121,7 +121,7 @@
121
121
  "auxiliaryFiles": [
122
122
  "33.js.map"
123
123
  ],
124
- "hash": "2bf9136ba0abb4d8",
124
+ "hash": "bc1c66c74f7d99bc",
125
125
  "childrenByOrder": {}
126
126
  },
127
127
  {
@@ -145,7 +145,7 @@
145
145
  "auxiliaryFiles": [
146
146
  "93.js.map"
147
147
  ],
148
- "hash": "bcb04e259b07cb83",
148
+ "hash": "59300aec830930b9",
149
149
  "childrenByOrder": {}
150
150
  },
151
151
  {
@@ -169,7 +169,7 @@
169
169
  "auxiliaryFiles": [
170
170
  "119.js.map"
171
171
  ],
172
- "hash": "9e0ece5b55d8b927",
172
+ "hash": "f95a0e820fecdb8a",
173
173
  "childrenByOrder": {}
174
174
  },
175
175
  {
@@ -220,7 +220,7 @@
220
220
  "auxiliaryFiles": [
221
221
  "152.js.map"
222
222
  ],
223
- "hash": "00aaf1426ecbea5b",
223
+ "hash": "2bc6d405b90a5461",
224
224
  "childrenByOrder": {}
225
225
  },
226
226
  {
@@ -244,7 +244,7 @@
244
244
  "auxiliaryFiles": [
245
245
  "172.js.map"
246
246
  ],
247
- "hash": "907bd3d7c926ba2e",
247
+ "hash": "88fa4b13d03dcc48",
248
248
  "childrenByOrder": {}
249
249
  },
250
250
  {
@@ -252,10 +252,10 @@
252
252
  "initial": true,
253
253
  "entry": true,
254
254
  "recorded": false,
255
- "size": 5613043,
255
+ "size": 5613135,
256
256
  "sizes": {
257
257
  "consume-shared": 210,
258
- "javascript": 5591513,
258
+ "javascript": 5591605,
259
259
  "share-init": 210,
260
260
  "runtime": 21110
261
261
  },
@@ -272,7 +272,7 @@
272
272
  "auxiliaryFiles": [
273
273
  "main.js.map"
274
274
  ],
275
- "hash": "7949965be8675f6a",
275
+ "hash": "d80163440b2e0cba",
276
276
  "childrenByOrder": {}
277
277
  },
278
278
  {
@@ -296,7 +296,7 @@
296
296
  "auxiliaryFiles": [
297
297
  "235.js.map"
298
298
  ],
299
- "hash": "189f7cff0509156c",
299
+ "hash": "97881173e5a445f1",
300
300
  "childrenByOrder": {}
301
301
  },
302
302
  {
@@ -342,7 +342,7 @@
342
342
  "auxiliaryFiles": [
343
343
  "290.js.map"
344
344
  ],
345
- "hash": "e892a72c4d88b49a",
345
+ "hash": "6818119ba0c530d7",
346
346
  "childrenByOrder": {}
347
347
  },
348
348
  {
@@ -434,7 +434,7 @@
434
434
  "auxiliaryFiles": [
435
435
  "467.js.map"
436
436
  ],
437
- "hash": "9971a8a2606f5583",
437
+ "hash": "eda382e4393e44d0",
438
438
  "childrenByOrder": {}
439
439
  },
440
440
  {
@@ -504,7 +504,7 @@
504
504
  "auxiliaryFiles": [
505
505
  "606.js.map"
506
506
  ],
507
- "hash": "de055858f3d1b0f1",
507
+ "hash": "7f242bd71b29a774",
508
508
  "childrenByOrder": {}
509
509
  },
510
510
  {
@@ -552,7 +552,7 @@
552
552
  "auxiliaryFiles": [
553
553
  "642.js.map"
554
554
  ],
555
- "hash": "0ff4c902817e1ac3",
555
+ "hash": "14b764133b014b57",
556
556
  "childrenByOrder": {}
557
557
  },
558
558
  {
@@ -597,7 +597,7 @@
597
597
  "auxiliaryFiles": [
598
598
  "675.js.map"
599
599
  ],
600
- "hash": "56496672eaa23ddf",
600
+ "hash": "e24ac0c50e7eb51e",
601
601
  "childrenByOrder": {}
602
602
  },
603
603
  {
@@ -621,7 +621,7 @@
621
621
  "auxiliaryFiles": [
622
622
  "703.js.map"
623
623
  ],
624
- "hash": "ee5dd12815fcdaae",
624
+ "hash": "c3acf7294d0d00f4",
625
625
  "childrenByOrder": {}
626
626
  },
627
627
  {
@@ -648,30 +648,6 @@
648
648
  "hash": "5abd4259c621a893",
649
649
  "childrenByOrder": {}
650
650
  },
651
- {
652
- "rendered": true,
653
- "initial": false,
654
- "entry": false,
655
- "recorded": false,
656
- "size": 331228,
657
- "sizes": {
658
- "javascript": 331228
659
- },
660
- "names": [],
661
- "idHints": [],
662
- "runtime": [
663
- "@openmrs/esm-stock-management-app",
664
- "main"
665
- ],
666
- "files": [
667
- "727.js"
668
- ],
669
- "auxiliaryFiles": [
670
- "727.js.map"
671
- ],
672
- "hash": "2cdbfbc571536659",
673
- "childrenByOrder": {}
674
- },
675
651
  {
676
652
  "rendered": true,
677
653
  "initial": false,
@@ -810,7 +786,7 @@
810
786
  "auxiliaryFiles": [
811
787
  "842.js.map"
812
788
  ],
813
- "hash": "7f297458351c949a",
789
+ "hash": "bc573a8612cda582",
814
790
  "childrenByOrder": {}
815
791
  },
816
792
  {
@@ -839,6 +815,30 @@
839
815
  ],
840
816
  "hash": "0b62e4cea3cb991b",
841
817
  "childrenByOrder": {}
818
+ },
819
+ {
820
+ "rendered": true,
821
+ "initial": false,
822
+ "entry": false,
823
+ "recorded": false,
824
+ "size": 338735,
825
+ "sizes": {
826
+ "javascript": 338735
827
+ },
828
+ "names": [],
829
+ "idHints": [],
830
+ "runtime": [
831
+ "@openmrs/esm-stock-management-app",
832
+ "main"
833
+ ],
834
+ "files": [
835
+ "987.js"
836
+ ],
837
+ "auxiliaryFiles": [
838
+ "987.js.map"
839
+ ],
840
+ "hash": "72ba819e6017e783",
841
+ "childrenByOrder": {}
842
842
  }
843
843
  ]
844
844
  }
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"stock-nav-menu","slot":"stock-sidebar-slot","component":"stockNavMenu","online":true,"offline":true},{"name":"overview-db-link","slot":"stock-page-dashboard-slot","component":"stockOverviewLink","meta":{"name":"overview","slot":"overview-dashboard-slot","title":"overview"},"order":0,"online":true,"offline":true},{"name":"stock-overview-db","slot":"overview-dashboard-slot","component":"stockOverview"},{"name":"operations-db-link","slot":"stock-page-dashboard-slot","component":"stockOperationsLink","meta":{"name":"operations","slot":"operations-dashboard-slot","title":"operations"},"order":2,"online":true,"offline":true},{"name":"stock-operations-db","slot":"operations-dashboard-slot","component":"stockOperations"},{"name":"items-db-link","slot":"stock-page-dashboard-slot","component":"stockItemsLink","meta":{"name":"items","slot":"items-dashboard-slot","title":"items"},"order":1,"online":true,"offline":true},{"name":"stock-items-db","slot":"items-dashboard-slot","component":"stockItems"},{"name":"user-scopes-db-link","slot":"stock-page-dashboard-slot","component":"stockUserScopesLink","meta":{"name":"user-scopes","slot":"user-scopes-dashboard-slot","title":"user-scopes"},"order":3,"online":true,"offline":true},{"name":"stock-user-scopes-db","slot":"user-scopes-dashboard-slot","component":"stockUserScopes"},{"name":"sources-db-link","slot":"stock-page-dashboard-slot","component":"stockSourcesLink","meta":{"name":"sources","slot":"sources-dashboard-slot","title":"Sources"},"order":2,"online":true,"offline":true},{"name":"stock-sources-db","slot":"sources-dashboard-slot","component":"stockSources"},{"name":"reports-db-link","slot":"stock-page-dashboard-slot","component":"stockReportsLink","meta":{"name":"reports","slot":"reports-dashboard-slot","title":"Reports"},"order":5,"online":true,"offline":true},{"name":"stock-reports-db","slot":"reports-dashboard-slot","component":"stockReports"},{"name":"settings-db-link","slot":"stock-page-dashboard-slot","component":"stockSettingsLink","meta":{"name":"settings","slot":"settings-dashboard-slot","title":"Settings"},"order":6,"online":true,"offline":true},{"name":"stock-settings-db","slot":"settings-dashboard-slot","component":"stockSettings"},{"name":"stock-management-admin-card-link","slot":"system-admin-page-card-link-slot","component":"stockManagementAdminCardLink"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"modals":[{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"expired-stock-modal","component":"expiredStockModal"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsModal"},{"name":"receiving-stock-modal","component":"receivingStockModal"},{"name":"stock-operation-dialog","component":"stockOperationModal"},{"name":"transactions-print-bincard-preview-modal","component":"transactionBincardPrintPreviewModal"},{"name":"transactions-print-stockcard-preview-modal","component":"transactionStockcardPrintPreviewModal"}],"workspaces":[{"name":"stock-operation-form-workspace","component":"stockOperationFormWorkspace","title":"Stock Operation","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-item-rules-form-workspace","component":"stockItemRulesFormWorkspace","title":"Stock Item Rules","type":"form"},{"name":"stock-item-form-workspace","component":"stockItemFormWorkspace","title":"Stock Items","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-sources-form-workspace","component":"stockSourcesFormWorkspace","title":"Stock Sources","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-location-form-workspace","component":"stockLocationsFormWorkspace","title":"Stock Locations","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-user-role-scopes-form-workspace","component":"stockUserScopesFormWorkspace","title":"User Role Scopes","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-reports-form-workspace","component":"stockReportsFormWorkspace","title":"Reports","type":"form","canMaximize":true,"width":"extra-wide"}],"pages":[{"component":"root","route":"stock-management"}],"version":"3.0.1-pre.865"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"stock-nav-menu","slot":"stock-sidebar-slot","component":"stockNavMenu","online":true,"offline":true},{"name":"overview-db-link","slot":"stock-page-dashboard-slot","component":"stockOverviewLink","meta":{"name":"overview","slot":"overview-dashboard-slot","title":"overview"},"order":0,"online":true,"offline":true},{"name":"stock-overview-db","slot":"overview-dashboard-slot","component":"stockOverview"},{"name":"operations-db-link","slot":"stock-page-dashboard-slot","component":"stockOperationsLink","meta":{"name":"operations","slot":"operations-dashboard-slot","title":"operations"},"order":2,"online":true,"offline":true},{"name":"stock-operations-db","slot":"operations-dashboard-slot","component":"stockOperations"},{"name":"items-db-link","slot":"stock-page-dashboard-slot","component":"stockItemsLink","meta":{"name":"items","slot":"items-dashboard-slot","title":"items"},"order":1,"online":true,"offline":true},{"name":"stock-items-db","slot":"items-dashboard-slot","component":"stockItems"},{"name":"user-scopes-db-link","slot":"stock-page-dashboard-slot","component":"stockUserScopesLink","meta":{"name":"user-scopes","slot":"user-scopes-dashboard-slot","title":"user-scopes"},"order":3,"online":true,"offline":true},{"name":"stock-user-scopes-db","slot":"user-scopes-dashboard-slot","component":"stockUserScopes"},{"name":"sources-db-link","slot":"stock-page-dashboard-slot","component":"stockSourcesLink","meta":{"name":"sources","slot":"sources-dashboard-slot","title":"Sources"},"order":2,"online":true,"offline":true},{"name":"stock-sources-db","slot":"sources-dashboard-slot","component":"stockSources"},{"name":"reports-db-link","slot":"stock-page-dashboard-slot","component":"stockReportsLink","meta":{"name":"reports","slot":"reports-dashboard-slot","title":"Reports"},"order":5,"online":true,"offline":true},{"name":"stock-reports-db","slot":"reports-dashboard-slot","component":"stockReports"},{"name":"settings-db-link","slot":"stock-page-dashboard-slot","component":"stockSettingsLink","meta":{"name":"settings","slot":"settings-dashboard-slot","title":"Settings"},"order":6,"online":true,"offline":true},{"name":"stock-settings-db","slot":"settings-dashboard-slot","component":"stockSettings"},{"name":"stock-management-admin-card-link","slot":"system-admin-page-card-link-slot","component":"stockManagementAdminCardLink"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"modals":[{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"expired-stock-modal","component":"expiredStockModal"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsModal"},{"name":"receiving-stock-modal","component":"receivingStockModal"},{"name":"stock-operation-dialog","component":"stockOperationModal"},{"name":"transactions-print-bincard-preview-modal","component":"transactionBincardPrintPreviewModal"},{"name":"transactions-print-stockcard-preview-modal","component":"transactionStockcardPrintPreviewModal"}],"workspaces":[{"name":"stock-operation-form-workspace","component":"stockOperationFormWorkspace","title":"Stock Operation","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-item-rules-form-workspace","component":"stockItemRulesFormWorkspace","title":"Stock Item Rules","type":"form"},{"name":"stock-item-form-workspace","component":"stockItemFormWorkspace","title":"Stock Items","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-sources-form-workspace","component":"stockSourcesFormWorkspace","title":"Stock Sources","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-location-form-workspace","component":"stockLocationsFormWorkspace","title":"Stock Locations","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-user-role-scopes-form-workspace","component":"stockUserScopesFormWorkspace","title":"User Role Scopes","type":"form","canMaximize":true,"width":"extra-wide"},{"name":"stock-reports-form-workspace","component":"stockReportsFormWorkspace","title":"Reports","type":"form","canMaximize":true,"width":"extra-wide"}],"pages":[{"component":"root","route":"stock-management"}],"version":"3.0.1-pre.868"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-stock-management-app",
3
- "version": "3.0.1-pre.865",
3
+ "version": "3.0.1-pre.868",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Stock management microfrontend for OpenMRS 3.x",
6
6
  "browser": "dist/openmrs-esm-stock-management-app.js",
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useEffect, useMemo } from 'react';
2
2
  import { ComboBox, InlineNotification, SkeletonText } from '@carbon/react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { type StockItemPackagingUOMDTO } from '../../../core/api/types/stockItem/StockItemPackagingUOM';
@@ -15,9 +15,14 @@ const QtyUomSelector: React.FC<QtyUomSelectorProps> = ({ stockItemUuid, error, i
15
15
  const { t } = useTranslation();
16
16
  const { isLoading, error: stockItemError, item } = useStockItem(stockItemUuid);
17
17
  const initialSelectedItem = useMemo<StockItemPackagingUOMDTO | null>(
18
- () => (item?.packagingUnits ?? []).find((u) => u.uuid === intiallvalue),
18
+ () => (item?.packagingUnits ?? []).find((u) => u.uuid === intiallvalue) ?? item?.packagingUnits?.[0],
19
19
  [item?.packagingUnits, intiallvalue],
20
20
  );
21
+ useEffect(() => {
22
+ if (initialSelectedItem) {
23
+ onValueChange?.(initialSelectedItem?.uuid);
24
+ }
25
+ }, [initialSelectedItem, onValueChange]);
21
26
 
22
27
  if (isLoading) return <SkeletonText role="progressbar" />;
23
28
 
@@ -38,7 +43,7 @@ const QtyUomSelector: React.FC<QtyUomSelectorProps> = ({ stockItemUuid, error, i
38
43
  invalidText={error}
39
44
  items={item?.packagingUnits ?? []}
40
45
  itemToString={(s: StockItemPackagingUOMDTO) =>
41
- s.packagingUomName ? `${s?.packagingUomName} - ${s?.factor} ` : ''
46
+ s?.packagingUomName ? `${s?.packagingUomName} - ${s?.factor} ` : ''
42
47
  }
43
48
  name={'stockItemPackagingUOMUuid'}
44
49
  onChange={(data: { selectedItem?: StockItemPackagingUOMDTO }) => {
@@ -34,6 +34,7 @@ const UniqueBatchNoEntryInput: React.FC<UniqueBatchNoEntryInputProps> = ({
34
34
  useEffect(() => {
35
35
  if (batchNoAlreadyUsed) {
36
36
  setError(t('batchNumberAlreadyUsed', 'Batch number already used'));
37
+ onValueChange?.('');
37
38
  } else {
38
39
  setError(undefined);
39
40
  onValueChange?.(value);
@@ -41,6 +41,11 @@ jest.mock('../stock-operations.resource', () => ({
41
41
  isLoading: false,
42
42
  error: null,
43
43
  }),
44
+ useStockOperationAndItems: jest.fn().mockReturnValue({
45
+ items: { results: [] },
46
+ isLoading: false,
47
+ error: null,
48
+ }),
44
49
  }));
45
50
 
46
51
  jest.mock('../../core/components/overlay/hook', () => ({
@@ -88,6 +93,7 @@ jest.mock('react-hook-form', () => ({
88
93
  getValues: jest.fn(),
89
94
  setValue: jest.fn(),
90
95
  handleSubmit: jest.fn(),
96
+ trigger: jest.fn().mockReturnValue(true),
91
97
  }),
92
98
  useFormContext: jest.fn().mockReturnValue({
93
99
  watch: jest.fn(),
@@ -109,6 +115,7 @@ jest.mock('react-hook-form', () => ({
109
115
  getValues: jest.fn(),
110
116
  setValue: jest.fn(),
111
117
  handleSubmit: jest.fn(),
118
+ trigger: jest.fn().mockReturnValue(true),
112
119
  }),
113
120
  Controller: ({ render }) => render({ field: {}, fieldState: {} }),
114
121
  FormProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
@@ -354,6 +361,7 @@ describe('Stock Operation step 2 (stock operation items details)', () => {
354
361
  getValues: jest.fn(),
355
362
  setValue: jest.fn(),
356
363
  handleSubmit: jest.fn(),
364
+ trigger: jest.fn().mockReturnValue(true),
357
365
  } as unknown as UseFormReturn<BaseStockOperationItemFormData>);
358
366
 
359
367
  render(
@@ -75,6 +75,7 @@ jest.mock('react-hook-form', () => ({
75
75
  getValues: jest.fn(),
76
76
  setValue: jest.fn(),
77
77
  handleSubmit: jest.fn(),
78
+ trigger: jest.fn().mockReturnValue(true),
78
79
  }),
79
80
  useFormContext: jest.fn().mockReturnValue({
80
81
  watch: jest.fn(),
@@ -85,6 +86,7 @@ jest.mock('react-hook-form', () => ({
85
86
  getValues: jest.fn(),
86
87
  setValue: jest.fn(),
87
88
  handleSubmit: jest.fn(),
89
+ trigger: jest.fn().mockReturnValue(true),
88
90
  }),
89
91
  Controller: ({ render }) => render({ field: {}, fieldState: {} }),
90
92
  FormProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
@@ -9,9 +9,10 @@ import {
9
9
  TextArea,
10
10
  TextInput,
11
11
  } from '@carbon/react';
12
+ import { ArrowRight } from '@carbon/react/icons';
12
13
  import { ErrorState } from '@openmrs/esm-framework';
13
14
  import React, { type ChangeEvent, type FC, useEffect, useMemo } from 'react';
14
- import { Controller, useFormContext, useFormState } from 'react-hook-form';
15
+ import { Controller, useFormContext } from 'react-hook-form';
15
16
  import { useTranslation } from 'react-i18next';
16
17
  import { DATE_PICKER_CONTROL_FORMAT, DATE_PICKER_FORMAT, MAIN_STORE_LOCATION_TAG } from '../../../constants';
17
18
  import { type Party } from '../../../core/api/types/Party';
@@ -23,7 +24,6 @@ import useParties from '../hooks/useParties';
23
24
  import StockOperationReasonSelector from '../input-components/stock-operation-reason-selector.component';
24
25
  import UsersSelector from '../input-components/users-selector.component';
25
26
  import styles from '../stock-operation-form.scss';
26
- import { ArrowRight } from '@carbon/react/icons';
27
27
 
28
28
  type BaseOperationDetailsFormStepProps = {
29
29
  stockOperation?: StockOperationDTO;
@@ -51,6 +51,18 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
51
51
  () => OperationType.STOCK_ISSUE_OPERATION_TYPE === stockOperationType.operationType,
52
52
  [stockOperationType],
53
53
  );
54
+ const handleNext = async () => {
55
+ const valid = await form.trigger([
56
+ 'responsiblePersonUuid',
57
+ 'operationDate',
58
+ 'remarks',
59
+ 'sourceUuid',
60
+ 'destinationUuid',
61
+ 'reasonUuid',
62
+ 'responsiblePersonOther',
63
+ ]);
64
+ if (valid) onNext();
65
+ };
54
66
 
55
67
  // initialize location fields
56
68
  useEffect(() => {
@@ -142,7 +154,7 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
142
154
  <ComboBox
143
155
  titleText={
144
156
  isStockIssueOperation
145
- ? t('destination', 'destination')
157
+ ? t('source', 'Source')
146
158
  : stockOperationType?.hasDestination || stockOperation?.destinationUuid
147
159
  ? t('from', 'From')
148
160
  : t('location', 'Location')
@@ -155,7 +167,6 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
155
167
  onChange={(data: { selectedItem: Party }) => {
156
168
  field.onChange(data.selectedItem?.uuid);
157
169
  }}
158
- initialSelectedItem={sourceParties.find((p) => p.uuid === field.value)}
159
170
  selectedItem={sourceParties.find((p) => p.uuid === field.value)}
160
171
  itemToString={(item?: Party) => (item && item?.name ? `${item?.name}` : '')}
161
172
  shouldFilterItem={() => true}
@@ -181,7 +192,7 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
181
192
  readOnly={field.disabled}
182
193
  titleText={
183
194
  isStockIssueOperation
184
- ? t('source', 'Source')
195
+ ? t('destination', 'destination')
185
196
  : stockOperationType?.hasSource || stockOperation?.atLocationUuid
186
197
  ? t('to', 'To')
187
198
  : t('location', 'Location')
@@ -193,7 +204,6 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
193
204
  onChange={(data: { selectedItem: Party }) => {
194
205
  field.onChange(data.selectedItem?.uuid);
195
206
  }}
196
- initialSelectedItem={destinationParties.find((p) => p.uuid === field.value)}
197
207
  selectedItem={destinationParties.find((p) => p.uuid === field.value)}
198
208
  itemToString={(item?: Party) => (item && item?.name ? `${item?.name}` : '')}
199
209
  shouldFilterItem={() => true}
@@ -240,7 +250,7 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
240
250
  </Column>
241
251
  <div className={styles.btnSet}>
242
252
  {typeof onNext === 'function' && (
243
- <Button kind="primary" onClick={onNext} role="button" renderIcon={ArrowRight}>
253
+ <Button kind="primary" onClick={handleNext} role="button" renderIcon={ArrowRight}>
244
254
  {t('next', 'Next')}
245
255
  </Button>
246
256
  )}
@@ -25,6 +25,7 @@ import StockOperationItemBatchNoCell from './stock-operation-item-batch-no-cell.
25
25
  import StockOperationItemCell from './stock-operation-item-cell.component';
26
26
  import StockoperationItemExpiryCell from './stock-operation-item-expiry-cell.component';
27
27
  import styles from './stock-operation-items-form-step.scc.scss';
28
+ import { showSnackbar } from '@openmrs/esm-framework';
28
29
 
29
30
  type StockOperationItemsFormStepProps = {
30
31
  stockOperation?: StockOperationDTO;
@@ -104,13 +105,6 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
104
105
  ];
105
106
  }, [operationTypePermision, t]);
106
107
 
107
- const handleDeleteStockOperationItem = useCallback(
108
- (item: BaseStockOperationItemFormData) => {
109
- form.setValue('stockOperationItems', observableOperationItems.filter((i) => i.uuid !== item.uuid) as any);
110
- },
111
- [form, observableOperationItems],
112
- );
113
-
114
108
  const tableRows = useMemo(() => {
115
109
  return observableOperationItems?.map((item, index) => {
116
110
  const {
@@ -181,6 +175,22 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
181
175
  });
182
176
  }, [observableOperationItems, onLaunchItemsForm, stockOperationType, uniqueId]);
183
177
 
178
+ const handleNext = async () => {
179
+ const valid = await form.trigger(['stockOperationItems']);
180
+ if (valid) {
181
+ onNext();
182
+ } else {
183
+ showSnackbar({
184
+ kind: 'error',
185
+ title: 'Validation error',
186
+ subtitle:
187
+ observableOperationItems && observableOperationItems.length > 0
188
+ ? 'You must update batch infomation for items'
189
+ : 'You must add atleast one item',
190
+ });
191
+ }
192
+ };
193
+
184
194
  const headerTitle = t('stockoperationItems', 'Stock operation items');
185
195
 
186
196
  return (
@@ -239,7 +249,7 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
239
249
  />
240
250
  <div className={styles.btnSet}>
241
251
  {typeof onNext === 'function' && (
242
- <Button kind="primary" onClick={onNext} renderIcon={ArrowRight}>
252
+ <Button kind="primary" onClick={handleNext} renderIcon={ArrowRight}>
243
253
  {t('next', 'Next')}
244
254
  </Button>
245
255
  )}
@@ -127,7 +127,9 @@ const StockItemForm: React.FC<StockItemFormProps> = ({ stockOperationType, stock
127
127
  locale="en"
128
128
  className={styles.datePickerInput}
129
129
  dateFormat={DATE_PICKER_CONTROL_FORMAT}
130
- {...field}
130
+ value={field.value}
131
+ name={field.name}
132
+ disabled={field.disabled}
131
133
  onChange={([newDate]) => {
132
134
  field.onChange(newDate);
133
135
  }}
@@ -139,6 +141,7 @@ const StockItemForm: React.FC<StockItemFormProps> = ({ stockOperationType, stock
139
141
  placeholder={DATE_PICKER_FORMAT}
140
142
  labelText={t('expiriation', 'Expiration Date')}
141
143
  invalid={error?.message}
144
+ invalidText={error?.message}
142
145
  />
143
146
  </DatePicker>
144
147
  )}
@@ -26,9 +26,9 @@ import BaseOperationDetailsFormStep from './steps/base-operation-details-form-st
26
26
  import ReceivedItems from './steps/received-items.component';
27
27
  import StockOperationItemsFormStep from './steps/stock-operation-items-form-step.component';
28
28
  import StockOperationSubmissionFormStep from './steps/stock-operation-submission-form-step.component';
29
- import StockIssueFormInitializerWithRelatedRequisitionOperation from './stock-issue-form-initializer-with-related-requisition-operation.component';
30
29
  import StockItemForm, { type StockItemFormProps } from './stock-item-form/stock-item-form.workspace';
31
30
  import StockOperationStepper from './stock-operation-stepper/stock-operation-stepper.component';
31
+ import { useStockOperationAndItems } from '../stock-operations.resource';
32
32
 
33
33
  /**
34
34
  * Props interface for the StockOperationForm component
@@ -72,6 +72,8 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
72
72
  user: { uuid: defaultLoggedUserUuid },
73
73
  } = useSession();
74
74
  const { autoPopulateResponsiblePerson } = useConfig<ConfigObject>();
75
+ const { error, items: _stockOperation, isLoading } = useStockOperationAndItems(stockRequisitionUuid);
76
+
75
77
  const form = useForm<StockOperationItemDtoSchema>({
76
78
  defaultValues: {
77
79
  responsiblePersonUuid:
@@ -95,6 +97,23 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
95
97
  destinationUuid: stockOperation?.destinationUuid ?? '',
96
98
  },
97
99
  mode: 'all',
100
+ values: stockRequisitionUuid
101
+ ? {
102
+ sourceUuid: _stockOperation?.destinationUuid,
103
+ destinationUuid: _stockOperation?.sourceUuid,
104
+ operationTypeUuid: stockOperationType?.uuid,
105
+ stockOperationItems: (_stockOperation?.stockOperationItems?.map((item) =>
106
+ pick(
107
+ { ...item, expiration: item?.expiration ? parseDate(item.expiration as any) : undefined },
108
+ stockOperationItemFormSchema.keyof().options,
109
+ ),
110
+ ) ?? []) as any,
111
+ requisitionStockOperationUuid: stockRequisitionUuid,
112
+ responsiblePersonUuid: _stockOperation?.responsiblePersonUuid,
113
+ responsiblePersonOther: _stockOperation?.responsiblePersonOther,
114
+ operationDate: _stockOperation?.operationDate ? parseDate(_stockOperation!.operationDate as any) : today(),
115
+ }
116
+ : undefined,
98
117
  resolver: zodResolver(formschema),
99
118
  });
100
119
  const [renderItemForm, setRenderItemForm] = useState(false);
@@ -137,7 +156,7 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
137
156
  onNext={() => setSelectedIndex(1)}
138
157
  />
139
158
  ),
140
- disabled: false,
159
+ disabled: !stockOperation,
141
160
  },
142
161
  {
143
162
  name: t('stockItems', 'Stock Items'),
@@ -150,7 +169,7 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
150
169
  onLaunchItemsForm={handleLaunchStockItem}
151
170
  />
152
171
  ),
153
- disabled: false,
172
+ disabled: !stockOperation,
154
173
  },
155
174
  {
156
175
  name: operationTypePermision?.requiresDispatchAcknowledgement ? 'Submit/Dispatch' : 'Submit/Complete',
@@ -163,7 +182,7 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
163
182
  dismissWorkspace={closeWorkspace}
164
183
  />
165
184
  ),
166
- disabled: false,
185
+ disabled: !stockOperation,
167
186
  },
168
187
  ].concat(
169
188
  showReceivedItems
@@ -171,7 +190,7 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
171
190
  {
172
191
  name: t('receivedItems', 'Received Items'),
173
192
  component: <ReceivedItems stockOperation={stockOperation} onPrevious={() => setSelectedIndex(2)} />,
174
- disabled: false,
193
+ disabled: !stockOperation,
175
194
  },
176
195
  ]
177
196
  : [],
@@ -218,14 +237,25 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
218
237
  }
219
238
  }, [form.formState.errors]);
220
239
 
240
+ // Stock issue errors (while fetching related requisitio or if no supplied requisition)
241
+ useEffect(() => {
242
+ if (operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE && !stockRequisitionUuid)
243
+ showSnackbar({
244
+ kind: 'error',
245
+ title: t('stockIssueError', 'StockIssue error'),
246
+ subtitle: t('relatedStockRequisitionRequired', 'Related stock requisition Required'),
247
+ });
248
+ if (error) {
249
+ showSnackbar({
250
+ kind: 'error',
251
+ title: t('stockIssueError', 'StockIssue error'),
252
+ subtitle: error?.message,
253
+ });
254
+ }
255
+ }, [stockRequisitionUuid, error, t, operationType]);
256
+
221
257
  return (
222
258
  <FormProvider {...form}>
223
- {stockOperationType.operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE && (
224
- <StockIssueFormInitializerWithRelatedRequisitionOperation
225
- stockRequisitionUuid={stockRequisitionUuid as string}
226
- stockOperationType={stockOperationType}
227
- />
228
- )}
229
259
  {renderItemForm ? (
230
260
  <StockItemForm {...itemsFormProps} />
231
261
  ) : (
@@ -82,9 +82,9 @@ export function getStockOperation(id: string): Promise<FetchResponse<StockOperat
82
82
  }
83
83
 
84
84
  // getStockOperationAndItems
85
- export function useStockOperationAndItems(id: string) {
85
+ export function useStockOperationAndItems(id = '') {
86
86
  const apiUrl = `${restBaseUrl}/stockmanagement/stockoperation/${id}?v=full`;
87
- const { data, error, isLoading } = useSWR<{ data: StockOperationDTO }, Error>(apiUrl, openmrsFetch);
87
+ const { data, error, isLoading } = useSWR<{ data: StockOperationDTO }, Error>(id ? apiUrl : null, openmrsFetch);
88
88
  return {
89
89
  items: data?.data,
90
90
  isLoading,
@@ -143,6 +143,18 @@ export const getStockOperationItemFormSchema = (operationType: OperationType) =>
143
143
  purchasePrice: true,
144
144
  });
145
145
  case OperationType.ADJUSTMENT_OPERATION_TYPE:
146
+ return baseStockOperationItemSchema
147
+ .omit({
148
+ batchNo: true,
149
+ expiration: true,
150
+ purchasePrice: true,
151
+ })
152
+ .extend({
153
+ // Override quantity to allow negative values for negative adjustment operation
154
+ quantity: z.coerce.number().refine((value) => value !== 0, {
155
+ message: 'Quantity cannot be zero.',
156
+ }),
157
+ });
146
158
  case OperationType.DISPOSED_OPERATION_TYPE:
147
159
  case OperationType.RETURN_OPERATION_TYPE:
148
160
  case OperationType.STOCK_ISSUE_OPERATION_TYPE: