diff --git a/packages/apps/hr/src/api/index.ts b/packages/apps/hr/src/api/index.ts
index e260fafc4b..f132db5d49 100644
--- a/packages/apps/hr/src/api/index.ts
+++ b/packages/apps/hr/src/api/index.ts
@@ -45,6 +45,7 @@ export {searchExpenseType as searchExpenseTypeApi} from './expense-type-api';
export {searchKilometricAllowParam as searchKilometricAllowParamApi} from './kilometric-allow-param-api';
export {
cancelLeave as cancelLeaveApi,
+ deleteLeave as deleteLeaveApi,
fetchLeave as fetchLeaveApi,
fetchLeaveById as fetchLeaveByIdApi,
fetchLeaveReason as fetchLeaveReasonApi,
diff --git a/packages/apps/hr/src/api/leave-api.js b/packages/apps/hr/src/api/leave-api.js
index 1c37d9fd3a..e8c048ed2d 100644
--- a/packages/apps/hr/src/api/leave-api.js
+++ b/packages/apps/hr/src/api/leave-api.js
@@ -180,3 +180,15 @@ export async function rejectLeave({leaveRequestId, version, groundForRefusal}) {
description: 'reject leave',
});
}
+
+export async function deleteLeave({leaveRequestId}) {
+ return getActionApi().send({
+ url: `ws/rest/com.axelor.apps.hr.db.LeaveRequest/${leaveRequestId}`,
+ method: 'delete',
+ description: 'delete leave request',
+ matchers: {
+ modelName: 'com.axelor.apps.hr.db.LeaveRequest',
+ id: leaveRequestId,
+ },
+ });
+}
diff --git a/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx b/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx
index ed9cd1e418..22aae584c6 100644
--- a/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx
+++ b/packages/apps/hr/src/components/molecules/LeaveActionCard/LeaveActionCard.tsx
@@ -16,11 +16,15 @@
* along with this program. If not, see .
*/
-import React from 'react';
-import {useTranslator, useTypes} from '@axelor/aos-mobile-core';
+import React, {useMemo} from 'react';
+import {
+ usePermitted,
+ useSelector,
+ useTranslator,
+ useTypes,
+} from '@axelor/aos-mobile-core';
import {ActionCard} from '@axelor/aos-mobile-ui';
import {LeaveCard} from '../../atoms';
-import {Leave} from '../../../types';
interface LeaveActionCardProps {
mode: number;
@@ -39,26 +43,47 @@ const LeaveActionCard = ({
}: LeaveActionCardProps) => {
const I18n = useTranslator();
const {LeaveRequest} = useTypes();
+ const {readonly} = usePermitted({
+ modelName: 'com.axelor.apps.hr.db.LeaveRequest',
+ });
+
+ const {user} = useSelector((state: any) => state.user);
+
+ const userCanValidate = useMemo(() => {
+ return (
+ (user.employee?.hrManager ||
+ leave.employee?.managerUser?.id === user.id) &&
+ leave.statusSelect === LeaveRequest?.statusSelect.WaitingValidation
+ );
+ }, [LeaveRequest?.statusSelect.WaitingValidation, leave, user]);
+
+ const isDefaultDisplay = useMemo(() => {
+ return (
+ readonly ||
+ (!userCanValidate &&
+ leave.statusSelect !== LeaveRequest?.statusSelect.Draft)
+ );
+ }, [LeaveRequest?.statusSelect, readonly, leave, userCanValidate]);
return (
+ actionList={
+ !isDefaultDisplay && [
+ {
+ iconName: 'send-fill',
+ helper: I18n.t('Hr_Send'),
+ onPress: onSend,
+ hidden: leave.statusSelect !== LeaveRequest?.statusSelect.Draft,
+ },
+ {
+ iconName: 'check-lg',
+ helper: I18n.t('Hr_Validate'),
+ onPress: onValidate,
+ hidden: leave.statusSelect === LeaveRequest?.statusSelect.Draft,
+ },
+ ]
+ }>
{
const I18n = useTranslator();
const Colors = useThemeColor();
+ const navigation = useNavigation();
const dispatch = useDispatch();
const {LeaveRequest} = useTypes();
+ const {canDelete, readonly} = usePermitted({
+ modelName: 'com.axelor.apps.hr.db.LeaveRequest',
+ });
const [refusalPopupIsOpen, setRefusalPopupIsOpen] = useState(false);
@@ -55,49 +60,47 @@ const LeaveDetailsButtons = ({
const leaveRequestParams = useMemo(
() => ({
- leaveRequestId: leaveId,
- version: leaveVersion,
+ leaveRequestId: leaveRequest.id,
+ version: leaveRequest.version,
+ user: user,
+ userId: user.id,
}),
- [leaveId, leaveVersion],
+ [leaveRequest, user],
);
const sendLeaveAPI = useCallback(() => {
- dispatch(
- (sendLeave as any)({
- ...leaveRequestParams,
- userId: user?.id,
- }),
- );
- }, [dispatch, leaveRequestParams, user?.id]);
+ dispatch((sendLeave as any)(leaveRequestParams));
+ }, [dispatch, leaveRequestParams]);
const validateLeaveAPI = useCallback(() => {
- dispatch(
- (validateLeave as any)({
- ...leaveRequestParams,
- user: user,
- }),
- );
- }, [dispatch, leaveRequestParams, user]);
+ dispatch((validateLeave as any)(leaveRequestParams));
+ }, [dispatch, leaveRequestParams]);
const cancelLeaveAPI = useCallback(() => {
- dispatch(
- (cancelLeave as any)({
- ...leaveRequestParams,
- userId: user?.id,
- }),
- );
- }, [dispatch, leaveRequestParams, user?.id]);
+ dispatch((cancelLeave as any)(leaveRequestParams));
+ }, [dispatch, leaveRequestParams]);
+
+ const deleteLeaveAPI = useCallback(() => {
+ dispatch((deleteLeave as any)(leaveRequestParams));
+ navigation.pop();
+ }, [dispatch, leaveRequestParams, navigation]);
+
+ if (readonly) {
+ return null;
+ }
if (statusSelect === LeaveRequest?.statusSelect.Draft) {
return (
-
+ {canDelete && (
+
+ )}
+ );
+ }
+
return (
setRefusalPopupIsOpen(true)}
- width="45%"
+ title={I18n.t('Hr_Cancel')}
+ onPress={cancelLeaveAPI}
color={Colors.errorColor}
- iconName="x-lg"
- />
-
- setRefusalPopupIsOpen(false)}
+ iconName="trash3-fill"
/>
);
diff --git a/packages/apps/hr/src/components/templates/LeaveRefusalPopup/LeaveRefusalPopup.tsx b/packages/apps/hr/src/components/templates/LeaveRefusalPopup/LeaveRefusalPopup.tsx
index f55fd3cbf2..c4db348259 100644
--- a/packages/apps/hr/src/components/templates/LeaveRefusalPopup/LeaveRefusalPopup.tsx
+++ b/packages/apps/hr/src/components/templates/LeaveRefusalPopup/LeaveRefusalPopup.tsx
@@ -25,14 +25,14 @@ interface LeaveRefusalPopupProps {
isOpen: boolean;
leaveId: number;
leaveVersion: number;
- onCancel: () => void;
+ handleClose: () => void;
}
const LeaveRefusalPopup = ({
isOpen,
leaveId,
leaveVersion,
- onCancel,
+ handleClose,
}: LeaveRefusalPopupProps) => {
const dispatch = useDispatch();
@@ -40,22 +40,24 @@ const LeaveRefusalPopup = ({
const rejectLeaveAPI = useCallback(
(refusalMessage: string) => {
+ handleClose();
dispatch(
(rejectLeave as any)({
leaveRequestId: leaveId,
version: leaveVersion,
user: user,
+ userId: user.id,
groundForRefusal: refusalMessage,
}),
);
},
- [dispatch, leaveId, leaveVersion, user],
+ [dispatch, handleClose, leaveId, leaveVersion, user],
);
return (
);
diff --git a/packages/apps/hr/src/features/asyncFunctions-index.ts b/packages/apps/hr/src/features/asyncFunctions-index.ts
index 8efe78ea36..115295ce9a 100644
--- a/packages/apps/hr/src/features/asyncFunctions-index.ts
+++ b/packages/apps/hr/src/features/asyncFunctions-index.ts
@@ -53,6 +53,7 @@ export {
} from './kilometricAllowParamSlice';
export {
cancelLeave,
+ deleteLeave,
fetchLeave,
fetchLeaveById,
fetchLeaveReason,
diff --git a/packages/apps/hr/src/features/leaveSlice.js b/packages/apps/hr/src/features/leaveSlice.js
index 0dc18d90c1..386bec2f9d 100644
--- a/packages/apps/hr/src/features/leaveSlice.js
+++ b/packages/apps/hr/src/features/leaveSlice.js
@@ -23,6 +23,7 @@ import {
} from '@axelor/aos-mobile-core';
import {
cancelLeave as _cancelLeave,
+ deleteLeave as _deleteLeave,
fetchLeave as _fetchLeave,
fetchLeaveById as _fetchLeaveById,
fetchLeaveReason as _fetchLeaveReason,
@@ -94,12 +95,8 @@ export const sendLeave = createAsyncThunk(
getState,
responseOptions: {isArrayResponse: false},
}).then(() => {
- dispatch(
- fetchLeave({
- userId: data.userId,
- selectedStatus: data.selectedStatus,
- }),
- );
+ dispatch(fetchLeave(data));
+ dispatch(fetchLeaveToValidate({user: data.user}));
dispatch(fetchLeaveById({leaveId: data.leaveRequestId}));
});
},
@@ -115,6 +112,7 @@ export const validateLeave = createAsyncThunk(
getState,
responseOptions: {isArrayResponse: false},
}).then(() => {
+ dispatch(fetchLeave(data));
dispatch(fetchLeaveToValidate({user: data.user}));
dispatch(fetchLeaveById({leaveId: data.leaveRequestId}));
});
@@ -131,12 +129,8 @@ export const cancelLeave = createAsyncThunk(
getState,
responseOptions: {isArrayResponse: false},
}).then(() => {
- dispatch(
- fetchLeave({
- userId: data.userId,
- selectedStatus: data.selectedStatus,
- }),
- );
+ dispatch(fetchLeave(data));
+ dispatch(fetchLeaveToValidate({user: data.user}));
dispatch(fetchLeaveById({leaveId: data.leaveRequestId}));
});
},
@@ -152,12 +146,28 @@ export const rejectLeave = createAsyncThunk(
getState,
responseOptions: {isArrayResponse: false},
}).then(() => {
+ dispatch(fetchLeave(data));
dispatch(fetchLeaveToValidate({user: data.user}));
dispatch(fetchLeaveById({leaveId: data.leaveRequestId}));
});
},
);
+export const deleteLeave = createAsyncThunk(
+ 'hr_leave/deleteLeave',
+ async function (data, {getState, dispatch}) {
+ return handlerApiCall({
+ fetchFunction: _deleteLeave,
+ data,
+ action: 'Hr_SliceAction_DeleteLeave',
+ getState,
+ responseOptions: {isArrayResponse: false},
+ }).then(() => {
+ dispatch(fetchLeave(data));
+ });
+ },
+);
+
const initialState = {
loadingMyLeave: true,
moreLoadingMyLeave: false,
diff --git a/packages/apps/hr/src/i18n/en.json b/packages/apps/hr/src/i18n/en.json
index 1b0ce0f9c3..aa59c9c068 100644
--- a/packages/apps/hr/src/i18n/en.json
+++ b/packages/apps/hr/src/i18n/en.json
@@ -157,5 +157,6 @@
"Hr_SliceAction_SendLeave": "send leave",
"Hr_SliceAction_ValidateLeave": "validate leave",
"Hr_SliceAction_CancelLeave": "cancel leave",
- "Hr_SliceAction_RejectLeave": "reject leave"
+ "Hr_SliceAction_RejectLeave": "reject leave",
+ "Hr_SliceAction_DeleteLeave": "delete leave"
}
diff --git a/packages/apps/hr/src/i18n/fr.json b/packages/apps/hr/src/i18n/fr.json
index 5fd191a834..396b1b45ca 100644
--- a/packages/apps/hr/src/i18n/fr.json
+++ b/packages/apps/hr/src/i18n/fr.json
@@ -157,5 +157,6 @@
"Hr_SliceAction_SendLeave": "envoie de la demande de congé",
"Hr_SliceAction_ValidateLeave": "validation de la demande de congé",
"Hr_SliceAction_CancelLeave": "annulation de la demande de congé",
- "Hr_SliceAction_RejectLeave": "rejet de la demande de congé"
+ "Hr_SliceAction_RejectLeave": "rejet de la demande de congé",
+ "Hr_SliceAction_DeleteLeave": "suppression de la demande de congé"
}
diff --git a/packages/apps/hr/src/screens/leaveRequests/LeaveDetailsScreen.tsx b/packages/apps/hr/src/screens/leaveRequests/LeaveDetailsScreen.tsx
index 01798b6752..9e8afcdd8c 100644
--- a/packages/apps/hr/src/screens/leaveRequests/LeaveDetailsScreen.tsx
+++ b/packages/apps/hr/src/screens/leaveRequests/LeaveDetailsScreen.tsx
@@ -68,8 +68,7 @@ const LeaveDetailsScreen = ({route}) => {
fixedItems={
}>
{
[dispatch, selectedStatus, user?.id],
);
+ const getActionParams = useCallback(
+ (item: any) => ({
+ leaveRequestId: item.id,
+ version: item.version,
+ userId: user?.id,
+ user: user,
+ selectedStatus,
+ }),
+ [selectedStatus, user],
+ );
+
const sendLeaveAPI = useCallback(
- item => {
- dispatch(
- (sendLeave as any)({
- leaveRequestId: item.id,
- version: item.version,
- userId: user?.id,
- selectedStatus,
- }),
- );
+ (item: any) => {
+ dispatch((sendLeave as any)(getActionParams(item)));
},
- [dispatch, selectedStatus, user?.id],
+ [dispatch, getActionParams],
);
const validateLeaveApi = useCallback(
- item => {
- dispatch(
- (validateLeave as any)({
- leaveRequestId: item.id,
- version: item.version,
- user: user,
- selectedStatus,
- }),
- );
+ (item: any) => {
+ dispatch((validateLeave as any)(getActionParams(item)));
},
- [dispatch, selectedStatus, user],
+ [dispatch, getActionParams],
);
const fetchLeaveToValidateAPI = useCallback(