diff --git a/client/packages/common/src/intl/locales/en/common.json b/client/packages/common/src/intl/locales/en/common.json
index 5e9356b397..787885758d 100644
--- a/client/packages/common/src/intl/locales/en/common.json
+++ b/client/packages/common/src/intl/locales/en/common.json
@@ -284,6 +284,7 @@
"error.no-asset-view-permission": "You do not have permission to view assets.",
"error.no-customer-return-items": "No items have been added to this return.",
"error.no-customer-returns": "There are no Customer Returns to display.",
+ "error.no-create-outbound-shipment-permission": "You do not have permission to create an Outbound Shipment from a Requisition",
"error.no-data": "No data available",
"error.no-immunisation-programs": "No Immunization programs found",
"error.no-inbound-items": "No items have been added to this shipment.",
diff --git a/client/packages/common/src/types/schema.ts b/client/packages/common/src/types/schema.ts
index 93c8cb7ae2..b65bf2a90b 100644
--- a/client/packages/common/src/types/schema.ts
+++ b/client/packages/common/src/types/schema.ts
@@ -8907,6 +8907,7 @@ export enum UserPermission {
PrescriptionMutate = 'PRESCRIPTION_MUTATE',
PrescriptionQuery = 'PRESCRIPTION_QUERY',
Report = 'REPORT',
+ RequisitionCreateOutboundShipment = 'REQUISITION_CREATE_OUTBOUND_SHIPMENT',
RequisitionMutate = 'REQUISITION_MUTATE',
RequisitionQuery = 'REQUISITION_QUERY',
RequisitionSend = 'REQUISITION_SEND',
diff --git a/client/packages/requisitions/src/ResponseRequisition/DetailView/Footer/CreateShipmentButton.tsx b/client/packages/requisitions/src/ResponseRequisition/DetailView/Footer/CreateShipmentButton.tsx
index 605241d3e3..295bbffcd6 100644
--- a/client/packages/requisitions/src/ResponseRequisition/DetailView/Footer/CreateShipmentButton.tsx
+++ b/client/packages/requisitions/src/ResponseRequisition/DetailView/Footer/CreateShipmentButton.tsx
@@ -7,6 +7,8 @@ import {
useAlertModal,
RouteBuilder,
useNavigate,
+ useCallbackWithPermission,
+ UserPermission,
} from '@openmsupply-client/common';
import { useResponse } from '../../api';
import { AppRoute } from '@openmsupply-client/config/src';
@@ -55,11 +57,17 @@ export const CreateShipmentButtonComponent = () => {
}
};
+ const handleClick = useCallbackWithPermission(
+ UserPermission.RequisitionCreateOutboundShipment,
+ onCreateShipment,
+ t('error.no-create-outbound-shipment-permission')
+ );
+
return (
}
label={t('button.create-shipment')}
- onClick={onCreateShipment}
+ onClick={handleClick}
disabled={isDisabled}
color="secondary"
/>
diff --git a/server/graphql/requisition/src/mutations/response_requisition/create_requisition_shipment.rs b/server/graphql/requisition/src/mutations/response_requisition/create_requisition_shipment.rs
index 6eb92e0e4d..6591ca927b 100644
--- a/server/graphql/requisition/src/mutations/response_requisition/create_requisition_shipment.rs
+++ b/server/graphql/requisition/src/mutations/response_requisition/create_requisition_shipment.rs
@@ -48,7 +48,7 @@ pub fn create_requisition_shipment(
let user = validate_auth(
ctx,
&ResourceAccessRequest {
- resource: Resource::MutateRequisition,
+ resource: Resource::CreateOutboundShipmentFromRequisition,
store_id: Some(store_id.to_string()),
},
)?;
diff --git a/server/graphql/tests/permissions.rs b/server/graphql/tests/permissions.rs
index 43a82595b9..b01833c4b5 100644
--- a/server/graphql/tests/permissions.rs
+++ b/server/graphql/tests/permissions.rs
@@ -526,7 +526,7 @@ mod permission_tests {
}
}"#,
expected: ResourceAccessRequest {
- resource: Resource::MutateRequisition,
+ resource: Resource::CreateOutboundShipmentFromRequisition,
store_id: Some("some".to_string()),
},
},
diff --git a/server/graphql/types/src/types/permissions.rs b/server/graphql/types/src/types/permissions.rs
index a1caeefbee..7588da97dc 100644
--- a/server/graphql/types/src/types/permissions.rs
+++ b/server/graphql/types/src/types/permissions.rs
@@ -30,6 +30,7 @@ pub enum UserPermission {
RequisitionQuery,
RequisitionMutate,
RequisitionSend,
+ RequisitionCreateOutboundShipment,
RnRFormQuery,
RnRFormMutate,
OutboundShipmentQuery,
@@ -113,6 +114,9 @@ impl UserPermission {
PermissionType::InventoryAdjustmentMutate => UserPermission::InventoryAdjustmentMutate,
PermissionType::RequisitionQuery => UserPermission::RequisitionQuery,
PermissionType::RequisitionMutate => UserPermission::RequisitionMutate,
+ PermissionType::RequisitionCreateOutboundShipment => {
+ UserPermission::RequisitionCreateOutboundShipment
+ }
PermissionType::RnrFormQuery => UserPermission::RnRFormQuery,
PermissionType::RnrFormMutate => UserPermission::RnRFormMutate,
PermissionType::RequisitionSend => UserPermission::RequisitionSend,
@@ -164,6 +168,9 @@ impl UserPermission {
UserPermission::RequisitionQuery => PermissionType::RequisitionQuery,
UserPermission::RequisitionMutate => PermissionType::RequisitionMutate,
UserPermission::RequisitionSend => PermissionType::RequisitionSend,
+ UserPermission::RequisitionCreateOutboundShipment => {
+ PermissionType::RequisitionCreateOutboundShipment
+ }
UserPermission::RnRFormQuery => PermissionType::RnrFormQuery,
UserPermission::RnRFormMutate => PermissionType::RnrFormMutate,
UserPermission::OutboundShipmentQuery => PermissionType::OutboundShipmentQuery,
diff --git a/server/repository/src/db_diesel/user_permission_row.rs b/server/repository/src/db_diesel/user_permission_row.rs
index 62623b470b..ddc5f9e292 100644
--- a/server/repository/src/db_diesel/user_permission_row.rs
+++ b/server/repository/src/db_diesel/user_permission_row.rs
@@ -44,6 +44,7 @@ pub enum PermissionType {
RequisitionQuery,
RequisitionMutate,
RequisitionSend,
+ RequisitionCreateOutboundShipment,
// r&r form,
RnrFormQuery,
RnrFormMutate,
diff --git a/server/repository/src/migrations/v2_06_00/add_create_invoice_from_requisition_permission.rs b/server/repository/src/migrations/v2_06_00/add_create_invoice_from_requisition_permission.rs
new file mode 100644
index 0000000000..dce105474d
--- /dev/null
+++ b/server/repository/src/migrations/v2_06_00/add_create_invoice_from_requisition_permission.rs
@@ -0,0 +1,22 @@
+use crate::migrations::*;
+
+pub(crate) struct Migrate;
+
+impl MigrationFragment for Migrate {
+ fn identifier(&self) -> &'static str {
+ "add_create_invoice_from_requisition_permission"
+ }
+
+ fn migrate(&self, connection: &StorageConnection) -> anyhow::Result<()> {
+ if cfg!(feature = "postgres") {
+ sql!(
+ connection,
+ r#"
+ ALTER TYPE permission_type ADD VALUE IF NOT EXISTS 'REQUISITION_CREATE_OUTBOUND_SHIPMENT';
+ "#
+ )?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/server/repository/src/migrations/v2_06_00/mod.rs b/server/repository/src/migrations/v2_06_00/mod.rs
index 387112686b..076af22bd5 100644
--- a/server/repository/src/migrations/v2_06_00/mod.rs
+++ b/server/repository/src/migrations/v2_06_00/mod.rs
@@ -1,5 +1,6 @@
use super::{version::Version, Migration, MigrationFragment};
+mod add_create_invoice_from_requisition_permission;
mod add_index_to_sync_buffer;
mod add_program_deleted_datetime;
use crate::StorageConnection;
@@ -19,6 +20,7 @@ impl Migration for V2_06_00 {
vec![
Box::new(add_index_to_sync_buffer::Migrate),
Box::new(add_program_deleted_datetime::Migrate),
+ Box::new(add_create_invoice_from_requisition_permission::Migrate),
]
}
}
diff --git a/server/service/src/auth.rs b/server/service/src/auth.rs
index 425dfcb376..5aa22721af 100644
--- a/server/service/src/auth.rs
+++ b/server/service/src/auth.rs
@@ -67,6 +67,7 @@ pub enum Resource {
RequisitionChart,
RequisitionStats,
RequisitionSend,
+ CreateOutboundShipmentFromRequisition,
// stock take line
InsertStocktakeLine,
UpdateStocktakeLine,
@@ -335,6 +336,14 @@ fn all_permissions() -> HashMap {
PermissionDSL::HasPermission(PermissionType::RequisitionSend),
]),
);
+
+ map.insert(
+ Resource::CreateOutboundShipmentFromRequisition,
+ PermissionDSL::And(vec![
+ PermissionDSL::HasStoreAccess,
+ PermissionDSL::HasPermission(PermissionType::RequisitionCreateOutboundShipment),
+ ]),
+ );
// r&r form
map.insert(
Resource::QueryRnRForms,
diff --git a/server/service/src/login.rs b/server/service/src/login.rs
index f2fafd3180..eed7122370 100644
--- a/server/service/src/login.rs
+++ b/server/service/src/login.rs
@@ -448,6 +448,9 @@ fn permissions_to_domain(permissions: Vec) -> HashSet {
output.insert(PermissionType::RequisitionSend);
}
+ Permissions::CreateCustomerInvoicesFromRequisitions => {
+ output.insert(PermissionType::RequisitionCreateOutboundShipment);
+ }
// reports
Permissions::ViewReports => {
output.insert(PermissionType::Report);