Merge branch 'dev_odex25_hr' of https://github.com/expsa/odex25-standard-modules into bakry_hr

This commit is contained in:
Bakry 2024-11-27 17:03:40 +03:00
commit c26cb37c6f
59 changed files with 3708 additions and 337 deletions

View File

@ -1,107 +0,0 @@
name: App Server - Pull Code
# This Server contain many services:
# - Cyber project (dev - preprod)
# - Ensan project (dev - preprod)
# - Odex25-General Project (dev - preprod)
# - ODEX25_STANDARD Project (dev - preprod - prod)
# - Twahod Project (dev - preprod)
# - Helpdesk Project (dev - preprod)
on:
push:
branches:
- dev_odex-event
- dev_odex25_accounting
- dev_odex25_base
- dev_odex25_dms
- dev_odex25_fleet
- dev_odex25_ENSAN
- dev_odex25_hr
- dev_odex25_inventory
- dev_odex25_maintenance
- dev_odex25_mobile
- dev_odex25_pos
- dev_odex25_project
- dev_odex25_purchase
- dev_odex25_realstate
- dev_odex25_sales
- dev_odex25_survey
- dev_odex25_transactions
- dev_odex25_website
- dev_openeducat_erp-14.0.1.0
- dev_odex25_ensan
- preprod_odex-event
- preprod_odex25_accounting
- preprod_odex25_base
- preprod_odex25_dms
- preprod_odex25_fleet
- preprod_odex25_ENSAN
- preprod_odex25_hr
- preprod_odex25_inventory
- preprod_odex25_maintenance
- preprod_odex25_mobile
- preprod_odex25_pos
- preprod_odex25_project
- preprod_odex25_purchase
- preprod_odex25_realstate
- preprod_odex25_sales
- preprod_odex25_survey
- preprod_odex25_transactions
- preprod_odex25_website
- preprod_openeducat_erp-14.0.1.0
- preprod_odex25_ensan
workflow_dispatch:
jobs:
# deploy_master_server:
# name: Deploy to Master
# runs-on: app-sever-project-runner
# if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
# steps:
# - name: Checkout And Restart Project
# run: |
# echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
# sudo chmod +x ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
# sudo ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.APP_SERVER_USER14 }} ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }} ${{ secrets.CYBER_APP_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}
# if [ $? -eq 0 ]; then
# echo "** [INFO] "MASTER" services have been restarted."
# else
# echo "** [ERROR] Failed to restart "MASTER" services."
# fi
deploy_preprod_server:
name: Deploy to Preprod
runs-on: app-sever-project-runner
if: github.ref == 'refs/heads/preprod_odex-event' || github.ref == 'refs/heads/preprod_odex25_accounting' || github.ref == 'refs/heads/preprod_odex25_base' || github.ref == 'refs/heads/preprod_odex25_dms' || github.ref == 'refs/heads/preprod_odex25_fleet' || github.ref == 'refs/heads/preprod_odex25_ENSAN' || github.ref == 'refs/heads/preprod_odex25_hr' || github.ref == 'refs/heads/preprod_odex25_inventory' || github.ref == 'refs/heads/preprod_odex25_maintenance' || github.ref == 'refs/heads/preprod_odex25_mobile' || github.ref == 'refs/heads/preprod_odex25_pos' || github.ref == 'refs/heads/preprod_odex25_project' || github.ref == 'refs/heads/preprod_odex25_purchase' || github.ref == 'refs/heads/preprod_odex25_realstate' || github.ref == 'refs/heads/preprod_odex25_sales' || github.ref == 'refs/heads/preprod_odex25_survey' || github.ref == 'refs/heads/preprod_odex25_transactions' || github.ref == 'refs/heads/preprod_odex25_website' || github.ref == 'refs/heads/preprod_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/preprod_odex25_ensan'
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.APP_SERVER_USER14 }} ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }} ${{ secrets.CYBER_APP_PREPROD_SERVICE }} preprod ${GITHUB_REF#refs/heads/preprod_} ${GITHUB_REF#refs/heads/}
sudo systemctl restart ${{ secrets.ENSAN_APP_PREPROD_SERVICE }} ${{ secrets.ODEX25_GENERAL_PREPROD_SERVICE }} ${{ secrets.ODEX25_STANDARD_PREPROD_SERVICE }} ${{ secrets.TWAHOD_APP_PREPROD_SERVICE }} ${{ secrets.ODEX25_DEMO_PREPROD_SERVICE }} ${{ secrets.HELPDESK_PREPROD_SERVICE }} ${{ secrets.TRAHUM_PREPROD_SERVICE }}
if [ $? -eq 0 ]; then
echo "** [INFO] "PREPROD" services have been restarted."
else
echo "** [ERROR] Failed to restart "PREPROD" services."
fi
deploy_test_server:
name: Deploy to Test
runs-on: app-sever-project-runner
if: github.ref == 'refs/heads/dev_odex-event' || github.ref == 'refs/heads/dev_odex25_accounting' || github.ref == 'refs/heads/dev_odex25_base' || github.ref == 'refs/heads/dev_odex25_dms' || github.ref == 'refs/heads/dev_odex25_fleet' || github.ref == 'refs/heads/dev_odex25_ENSAN' || github.ref == 'refs/heads/dev_odex25_hr' || github.ref == 'refs/heads/dev_odex25_inventory' || github.ref == 'refs/heads/dev_odex25_maintenance' || github.ref == 'refs/heads/dev_odex25_mobile' || github.ref == 'refs/heads/dev_odex25_pos' || github.ref == 'refs/heads/dev_odex25_project' || github.ref == 'refs/heads/dev_odex25_purchase' || github.ref == 'refs/heads/dev_odex25_realstate' || github.ref == 'refs/heads/dev_odex25_sales' || github.ref == 'refs/heads/dev_odex25_survey' || github.ref == 'refs/heads/dev_odex25_transactions' || github.ref == 'refs/heads/dev_odex25_website' || github.ref == 'refs/heads/dev_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/dev_odex25_ensan'
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.APP_SERVER_USER14 }} ${{ secrets.APP_SERVER_STANDARD_FOLDER_PATH }} ${{ secrets.CYBER_APP_TEST_SERVICE }} test ${GITHUB_REF#refs/heads/dev_} ${GITHUB_REF#refs/heads/}
sudo systemctl restart ${{ secrets.ENSAN_APP_TEST_SERVICE }} ${{ secrets.ODEX25_GENERAL_TEST_SERVICE }} ${{ secrets.ODEX25_STANDARD_TEST_SERVICE }} ${{ secrets.TWAHOD_APP_TEST_SERVICE }} ${{ secrets.HELPDESK_TEST_SERVICE }} ${{ secrets.KAZ_LIBRARY_TEST_SERVICE }} ${{ secrets.TRAHUM_TEST_SERVICE }}
if [ $? -eq 0 ]; then
echo "** [INFO] "DEV" services have been restarted."
else
echo "** [ERROR] Failed to restart "DEV" services."
fi

View File

@ -1,18 +0,0 @@
name: Cyber Project - Pull Code
on:
workflow_dispatch:
jobs:
deploy_master_server:
name: Deploy to Master
runs-on: cyber-client-project-runner
if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.CYBER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.CYBER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.CYBER_PROJECT_USER }} ${{ secrets.CYBER_STANDARD_FOLDER_PATH }} ${{ secrets.CYBER_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}

View File

@ -0,0 +1,90 @@
name: Dev/Preprod Servers - Pull Code
on:
push:
branches:
- dev_odex-event
- dev_odex25_accounting
- dev_odex25_base
- dev_odex25_dms
- dev_odex25_fleet
- dev_odex25_ENSAN
- dev_odex25_hr
- dev_odex25_inventory
- dev_odex25_maintenance
- dev_odex25_mobile
- dev_odex25_pos
- dev_odex25_project
- dev_odex25_purchase
- dev_odex25_realstate
- dev_odex25_sales
- dev_odex25_survey
- dev_odex25_transactions
- dev_odex25_website
- dev_openeducat_erp-14.0.1.0
- dev_odex25_ensan
- preprod_odex-event
- preprod_odex25_accounting
- preprod_odex25_base
- preprod_odex25_dms
- preprod_odex25_fleet
- preprod_odex25_ENSAN
- preprod_odex25_hr
- preprod_odex25_inventory
- preprod_odex25_maintenance
- preprod_odex25_mobile
- preprod_odex25_pos
- preprod_odex25_project
- preprod_odex25_purchase
- preprod_odex25_realstate
- preprod_odex25_sales
- preprod_odex25_survey
- preprod_odex25_transactions
- preprod_odex25_website
- preprod_openeducat_erp-14.0.1.0
- preprod_odex25_ensan
workflow_dispatch:
inputs:
environment:
description: 'Select Server'
required: true
type: choice
options:
- dev
- preprod
default: dev
jobs:
deploy_preprod_server:
name: Deploy to Preprod Servers
runs-on: app-sever-project-runner
if: (github.ref == 'refs/heads/preprod_odex-event' || github.ref == 'refs/heads/preprod_odex25_accounting' || github.ref == 'refs/heads/preprod_odex25_base' || github.ref == 'refs/heads/preprod_odex25_dms' || github.ref == 'refs/heads/preprod_odex25_fleet' || github.ref == 'refs/heads/preprod_odex25_ENSAN' || github.ref == 'refs/heads/preprod_odex25_hr' || github.ref == 'refs/heads/preprod_odex25_inventory' || github.ref == 'refs/heads/preprod_odex25_maintenance' || github.ref == 'refs/heads/preprod_odex25_mobile' || github.ref == 'refs/heads/preprod_odex25_pos' || github.ref == 'refs/heads/preprod_odex25_project' || github.ref == 'refs/heads/preprod_odex25_purchase' || github.ref == 'refs/heads/preprod_odex25_realstate' || github.ref == 'refs/heads/preprod_odex25_sales' || github.ref == 'refs/heads/preprod_odex25_survey' || github.ref == 'refs/heads/preprod_odex25_transactions' || github.ref == 'refs/heads/preprod_odex25_website' || github.ref == 'refs/heads/preprod_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/preprod_odex25_ensan') || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'preprod')
steps:
- name: Checkout And Restart Project
run: |
sudo chmod +x /home/${{ secrets.CLIENT_USER }}/scripts/pull/preprod_pull_standard_code.sh
sudo /home/${{ secrets.CLIENT_USER }}/scripts/pull/preprod_pull_standard_code.sh
sudo systemctl restart ${{ secrets.ENSAN_APP_PREPROD_SERVICE }} ${{ secrets.ODEX25_GENERAL_PREPROD_SERVICE }} ${{ secrets.ODEX25_STANDARD_PREPROD_SERVICE }} ${{ secrets.TWAHOD_APP_PREPROD_SERVICE }} ${{ secrets.ODEX25_DEMO_PREPROD_SERVICE }} ${{ secrets.HELPDESK_PREPROD_SERVICE }} ${{ secrets.TRAHUM_PREPROD_SERVICE }} ${{ secrets.CYBER_APP_PREPROD_SERVICE }}
if [ $? -eq 0 ]; then
echo "** [INFO] "PREPROD" services have been restarted."
else
echo "** [ERROR] Failed to restart "PREPROD" services."
fi
deploy_test_server:
name: Deploy to Dev Servers
runs-on: app-sever-project-runner
if: (github.ref == 'refs/heads/dev_odex-event' || github.ref == 'refs/heads/dev_odex25_accounting' || github.ref == 'refs/heads/dev_odex25_base' || github.ref == 'refs/heads/dev_odex25_dms' || github.ref == 'refs/heads/dev_odex25_fleet' || github.ref == 'refs/heads/dev_odex25_ENSAN' || github.ref == 'refs/heads/dev_odex25_hr' || github.ref == 'refs/heads/dev_odex25_inventory' || github.ref == 'refs/heads/dev_odex25_maintenance' || github.ref == 'refs/heads/dev_odex25_mobile' || github.ref == 'refs/heads/dev_odex25_pos' || github.ref == 'refs/heads/dev_odex25_project' || github.ref == 'refs/heads/dev_odex25_purchase' || github.ref == 'refs/heads/dev_odex25_realstate' || github.ref == 'refs/heads/dev_odex25_sales' || github.ref == 'refs/heads/dev_odex25_survey' || github.ref == 'refs/heads/dev_odex25_transactions' || github.ref == 'refs/heads/dev_odex25_website' || github.ref == 'refs/heads/dev_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/dev_odex25_ensan') || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'dev')
steps:
- name: Checkout And Restart Project
run: |
sudo chmod +x /home/${{ secrets.CLIENT_USER }}/scripts/pull/dev_pull_standard_code.sh
sudo /home/${{ secrets.CLIENT_USER }}/scripts/pull/dev_pull_standard_code.sh
sudo systemctl restart ${{ secrets.ENSAN_APP_TEST_SERVICE }} ${{ secrets.ODEX25_GENERAL_TEST_SERVICE }} ${{ secrets.ODEX25_STANDARD_TEST_SERVICE }} ${{ secrets.TWAHOD_APP_TEST_SERVICE }} ${{ secrets.HELPDESK_TEST_SERVICE }} ${{ secrets.KAZ_LIBRARY_TEST_SERVICE }} ${{ secrets.TRAHUM_TEST_SERVICE }} ${{ secrets.CYBER_APP_TEST_SERVICE }}
if [ $? -eq 0 ]; then
echo "** [INFO] "DEV" services have been restarted."
else
echo "** [ERROR] Failed to restart "DEV" services."
fi

View File

@ -1,18 +0,0 @@
name: Ensan Project - Pull Code
on:
workflow_dispatch:
jobs:
deploy_master_server:
name: Deploy to Master
runs-on: ensan-client-project-runner
if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.ENSAN_PROJECT_USER }} ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }} ${{ secrets.ENSAN_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}

View File

@ -1,18 +0,0 @@
name: HELPDESK Project - Pull Code
on:
workflow_dispatch:
jobs:
deploy_master_server:
name: Deploy to Master
runs-on: helpdesk_server
if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.HELPDESK_PROJECT_USER }} ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }} ${{ secrets.HELPDESK_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}

View File

@ -1,18 +0,0 @@
name: KAZ-Library Project - Pull Code
on:
workflow_dispatch:
jobs:
deploy_master_server:
name: Deploy to Master
runs-on: kaz-library-project-runner
if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.KAZ_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.KAZ_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.KAZ_PROJECT_USER }} ${{ secrets.KAZ_STANDARD_FOLDER_PATH }} ${{ secrets.KAZ_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}

View File

@ -0,0 +1,86 @@
name: Production Projects - Pull Code
on:
workflow_dispatch:
inputs:
environment:
description: 'Select Project Prod Server'
required: true
type: choice
options:
- Cyber-Security-Project
- Ensan-Project
- Helpdesk-Khabir-Project
- King-AbdelAziz-Library-Project
- Twahod-Project
jobs:
# Cyber Project
cyber_master_server:
name: Deploy to Cyber Master
runs-on: cyber-client-project-runner
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Cyber-Security-Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
# if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Cyber-Security-Project'
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.CYBER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.CYBER_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.CYBER_PROJECT_USER }} ${{ secrets.CYBER_STANDARD_FOLDER_PATH }} ${{ secrets.CYBER_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}
# Ensan Project
ensan_master_server:
name: Deploy to Ensan Master
runs-on: ensan-client-project-runner
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Ensan-Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.ENSAN_PROJECT_USER }} ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }} ${{ secrets.ENSAN_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}
# Helpdesk Project
helpdesk_maser_server:
name: Deploy to Helpdesk Master
runs-on: helpdesk_server
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Helpdesk-Khabir-Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.HELPDESK_PROJECT_USER }} ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }} ${{ secrets.HELPDESK_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}
# King Abdel Aziz Lobrary project
kaz_master_server:
name: Deploy to KAZ Master
runs-on: kaz-library-project-runner
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'King-AbdelAziz-Library-Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.KAZ_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.KAZ_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.KAZ_PROJECT_USER }} ${{ secrets.KAZ_STANDARD_FOLDER_PATH }} ${{ secrets.KAZ_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}
# Twahod project
twahod_master_server:
name: Deploy to Twahod Master
runs-on: twahod-client-project-runner
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Twahod-Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.TWAHOD_PROJECT_USER }} ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }} ${{ secrets.TWAHOD_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}
# if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')

View File

@ -1,17 +0,0 @@
name: Twahod Project - Pull Code
on:
workflow_dispatch:
jobs:
deploy_master_server:
name: Deploy to Master
runs-on: twahod-client-project-runner
if: github.event_name == 'workflow_dispatch' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_ensan')
steps:
- name: Checkout And Restart Project
run: |
echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}"
sudo chmod +x ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh
sudo ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.TWAHOD_PROJECT_USER }} ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }} ${{ secrets.TWAHOD_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/}

View File

@ -13,6 +13,7 @@
'security/attendance_security.xml',
'security/ir.model.access.csv',
'data/ir_cron.xml',
'data/mail_template.xml',
'views/hr_attendance_report.xml',
'views/hr_attendance_transactions.xml',
'views/hr_lateness_reasons.xml',

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="hr_attendance_transaction_create" model="ir.cron">
<field name="name">Attendance Transaction</field>
<field name="model_id" ref="model_hr_attendance_transaction"/>
@ -44,14 +44,18 @@
<tr>
<td>${object.date.strftime('%Y-%m-%d')}</td>
<td>${object.date.strftime('%A')}</td>
<td>${object.lateness or 0}</td>
<td>${object.early_exit or 0}</td>
<td>${'Absent' if object.is_absent else 'Present'}</td>
<td>${'00:00:00' if not object.lateness else object.lateness.strftime('%H:%M:%S')}</td>
<td>${'00:00:00' if not object.early_exit else object.early_exit.strftime('%H:%M:%S')}</td>
<td>
${'Missed Punch' if (not object.sign_in or not object.sign_out) else ('Absent' if object.is_absent else 'Present')}
</td>
</tr>
</table>
<p>Please adhere to work timings. Thank you for your understanding.</p>
]]>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,36 @@
<odoo>
<!-- <record id="attendance_notification_email_template" model="mail.template">-->
<!-- <field name="name">Attendance Notification Email Template</field>-->
<!-- <field name="subject">Attendance Report</field>-->
<!-- <field name="email_from">${object.employee_id.work_email}</field>-->
<!-- <field name="model_id" ref="attendances.model_hr_attendance_transaction"/>-->
<!-- <field name="email_to">${object.email}</field>-->
<!-- <field name="lang">${object.lang}</field>-->
<!-- <field name="auto_delete" eval="False"/>-->
<!-- <field name="body_html">-->
<!-- <![CDATA[-->
<!-- <p>Dear ${object.employee_id.name},</p>-->
<!-- <p>We would like to inform you of the following attendance details:</p>-->
<!-- <table border="1" style="width:100%; border-collapse: collapse;">-->
<!-- <tr>-->
<!-- <th>Date</th>-->
<!-- <th>Daya</th>-->
<!-- <th>Lateness</th>-->
<!-- <th>Early Exit</th>-->
<!-- <th>Note</th>-->
<!-- </tr>-->
<!-- <tr>-->
<!-- <td>${object.date.strftime('%Y-%m-%d')}</td>-->
<!-- <td>${object.date.strftime('%A')}</td>-->
<!-- <td>${'00:00:00' if not object.lateness else object.lateness.strftime('%H:%M:%S')}</td>-->
<!-- <td>${'00:00:00' if not object.early_exit else object.early_exit.strftime('%H:%M:%S')}</td>-->
<!-- <td>-->
<!-- ${'Missed Punch' if (not object.sign_in or not object.sign_out) else ('Absent' if object.is_absent else 'Present')}-->
<!-- </td>-->
<!-- </tr>-->
<!-- </table>-->
<!-- <p>Please adhere to work timings. Thank you for your understanding.</p>-->
<!-- ]]>-->
<!-- </field>-->
<!-- </record>-->
</odoo>

View File

@ -54,13 +54,13 @@ class HrAttendanceTransactions(models.Model):
for item in self:
item.is_absent = False
item.approve_exit_out = False
item.is_official = False
item.total_absent_hours = 0
item.official_id = False
item.total_mission_hours = 0.0
item.approve_personal_permission = False
item.personal_permission_id = False
item.total_permission_hours = 0.0
# item.is_official = False
# item.total_absent_hours = 0
# item.official_id = False
# item.total_mission_hours = 0.0
# item.approve_personal_permission = False
# item.personal_permission_id = False
# item.total_permission_hours = 0.0
item.approve_lateness = False
item.lateness = False
item.early_exit = False
@ -1118,20 +1118,20 @@ class HrAttendanceTransactions(models.Model):
@api.model
def send_lateness_notifications(self):
yesterday = datetime.now().date() - timedelta(days=1)
records_to_notify = self.search([
('date', '=', yesterday), '|', '|',
('lateness', '>', 0),
('early_exit', '>', 0),
('is_absent', '=', True)
])
records_to_notify = self.search([('date', '=', yesterday)])
template_id = self.env.ref('attendances.attendance_notification_email_template').id
for record in records_to_notify:
if template_id:
template = self.env['mail.template'].browse(template_id)
template.send_mail(record.id, force_send=True)
if (
record.lateness > 0 or
record.early_exit > 0 or
record.is_absent or
(record.sign_out == 0 and record.sign_in != 0) or
(record.sign_out != 0 and record.sign_in == 0)
):
if template_id:
template = self.env['mail.template'].browse(template_id)
template.send_mail(record.id, force_send=True)
# @api.multi
# def unlink(self):
# raise UserError(_('Sorry, you can not delete an attendance transaction manually.'))

View File

@ -148,17 +148,6 @@
<field name="account_overtime_id" string="Account Overtime"/>
</group>
</page>
<page string="Permission Settings" name="over_time_full">
<group>
<group>
<field name="permission_hours" string="Hours Per Day" widget="float_time" help="The Minimum Permission Hours Per Day"/>
<field name="permission_number" string="Hours Per Month" widget="float_time" help="The Maximum Permission Hours per Month"/>
</group>
<group>
<field name = "approval_by"/>
</group>
</group>
</page>
</notebook>
<notebook attrs="{'invisible':[('is_full_day','=',True)]}">
<page string="Shift One">
@ -272,17 +261,6 @@
<field name="account_overtime_id" string="Account Overtime"/>
</group>
</page>
<page string="Permission Settings" name="over_time_not_full">
<group>
<group>
<field name="permission_hours" string="Hours Per Day" widget="float_time" help="The Minimum Permission Hours Per Day"/>
<field name="permission_number" string="Hours Per Month" widget="float_time" help="The Maximum Permission Hours per Month"/>
</group>
<group>
<field name = "approval_by"/>
</group>
</group>
</page>
</notebook>
</sheet>

View File

@ -15,10 +15,13 @@
'security/employee_requests_security.xml',
'security/ir.model.access.csv',
'data/hr_personal_permission_type_data.xml',
'views/employee_effective_form.xml',
'views/employee_overtime_request.xml',
'views/hr_clearance_form.xml',
'views/hr_personal_permission.xml',
'views/hr_personal_permission_type_views.xml',
'views/customize_hr_employee.xml',
'views/employee_department_jobs_view.xml',

View File

@ -0,0 +1,11 @@
<?xml version='1.0' encoding='utf-8'?>
<odoo>
<record id="seq_hr_personal_permission_type" model="ir.sequence">
<field name="name">Personal Permission Type Sequence</field>
<field name="code">hr.personal.permission.type.sequence</field>
<field name="prefix">PT-</field>
<field name="padding">4</field>
</record>
</odoo>

View File

@ -2369,8 +2369,8 @@ msgstr "إستئذان شخصي"
#. module: employee_requests
#: model:ir.ui.menu,name:employee_requests.employee_personal_permission_menu_item
msgid "Personal Permissions"
msgstr "إستئذان الخروج"
msgid "Permissions"
msgstr "الاذونات"
#. module: employee_requests
#: model_terms:ir.ui.view,arch_db:employee_requests.clearance_report_template
@ -3912,3 +3912,38 @@ msgstr "لايمكن طلب عمل إضافي للموظف %s بقيمة عمل
msgid "You can not Request Overtime The Employee %s The Overtime Amount Zero"
msgstr "لايمكن طلب عمل إضافي للموظف %s بقيمة عمل إضافي صفر."
#. module: employee_requests
#: model:ir.model.fields,field_description:employee_requests.field_hr_personal_permission_type__approval_by
msgid "Approval By"
msgstr "الموافقة من قبل"
#. module: employee_requests
#: model:ir.model.fields,field_description:employee_requests.field_hr_personal_permission__balance
#: model:ir.model.fields,field_description:employee_requests.field_hr_personal_permission_type__daily_hours
msgid "Daily Hours"
msgstr "الساعات اليومية"
#. module: employee_requests
#: model:ir.model.fields,field_description:employee_requests.field_hr_personal_permission__permission_type_id
#: model_terms:ir.ui.view,arch_db:employee_requests.employee_personal_permission_filter
#: model_terms:ir.ui.view,arch_db:employee_requests.hr_personal_permission_type_view_form
msgid "Permission Type"
msgstr "نوع الاستئذان"
#. module: employee_requests
#: model:ir.actions.act_window,name:employee_requests.action_permission_types
#: model:ir.ui.menu,name:employee_requests.menu_view_permission_types
#: model_terms:ir.ui.view,arch_db:employee_requests.hr_personal_permission_type_view_tree
msgid "Permission Types"
msgstr "أنواع الاستئذانات"
#. module: employee_requests
#: model:ir.model.fields,field_description:employee_requests.field_hr_personal_permission_type__monthly_hours
msgid "Monthly Hours"
msgstr "ساعات شهرية"
#. module: employee_requests
#: code:addons/employee_requests/models/hr_personal_permission.py:0
#, python-format
msgid "Date To must be on the same day as Date From."
msgstr "يجب أن يكون يوم تاريخ البداية هو نفسه يوم تاريخ النهاية."

View File

@ -3,6 +3,7 @@ from . import employee_effective_form
from . import employee_overtime_request
from . import hr_clearance_form
from . import document_directory
from . import hr_personal_permission_type
from . import hr_personal_permission
from . import house_allowance_advance
from . import employee

View File

@ -15,13 +15,14 @@ class HrPersonalPermission(models.Model):
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'date DESC'
permission_type_id = fields.Many2one('hr.personal.permission.type', required=True)
from_hr_department = fields.Boolean()
date = fields.Date(default=lambda self: fields.Date.today())
date_from = fields.Datetime()
date_to = fields.Datetime()
duration = fields.Float(compute='get_duration_no' ,store=True)
employee_contract_id = fields.Many2one(comodel_name='hr.contract.type')
balance = fields.Float(related='employee_id.contract_id.working_hours.permission_hours')
balance = fields.Float(related='permission_type_id.daily_hours')
permission_number = fields.Float(store=True, readonly=True, help='The Remaining Number of Hours permission This Month')
early_exit = fields.Boolean()
mission_purpose = fields.Text()
@ -89,6 +90,16 @@ class HrPersonalPermission(models.Model):
# return new_record
@api.constrains('date_from', 'date_to')
def _check_same_day(self):
for record in self:
if record.date_from and record.date_to:
# Check if date_to is on the same day as date_from
if record.date_from.date() != record.date_to.date():
raise ValidationError(
_("Date To must be on the same day as Date From.")
)
@api.constrains('date_from', 'date_to', 'employee_id')
def _check_attendance_hours(self):
for record in self:
@ -111,7 +122,7 @@ class HrPersonalPermission(models.Model):
def _get_duration_hours(self):
for item in self:
if item.date_from:
permission_hour = item.employee_id.resource_calendar_id.permission_hours
permission_hour = item.permission_type_id.daily_hours
start_date_hour = datetime.strptime(str(item.date_from), "%Y-%m-%d %H:%M:%S")
end_date_hour = start_date_hour + timedelta(hours=permission_hour)
item.date_to = end_date_hour
@ -131,7 +142,7 @@ class HrPersonalPermission(models.Model):
# function permission_number_decrement and _get_date_constrains replaced in new module hr permission holiday to fix
# singleton issue and change constrain
@api.onchange('date_to', 'date_from', 'employee_id')
@api.onchange('date_to', 'date_from', 'employee_id', 'permission_type_id')
def permission_number_decrement(self):
for item in self:
# item._onchange_time()
@ -148,9 +159,10 @@ class HrPersonalPermission(models.Model):
else:
date_to = (current_date.replace(month=current_month + 1, day=1) - timedelta(days=1)).strftime('%Y-%m-%d')
number_of_per = item.employee_id.contract_id.working_hours.permission_number
number_of_per = item.permission_type_id.monthly_hours
employee_permissions = self.search([
('employee_id', '=', item.employee_id.id),
('permission_type_id', '=', item.permission_type_id.id),
('state', 'not in', ('draft','refused')),
#('state', '=', 'approve'),
('date_from', '>=', date_from),
@ -164,7 +176,7 @@ class HrPersonalPermission(models.Model):
permission_date1 = rec.date_to.date() if isinstance(rec.date_to, datetime) else datetime.strptime(rec.date_to, DEFAULT_SERVER_DATETIME_FORMAT).date()
date_to_value1 = item.date_to.date() if isinstance(item.date_to, datetime) else datetime.strptime(item.date_to, DEFAULT_SERVER_DATETIME_FORMAT).date()
if permission_date1 == date_to_value1:
if permission_date1 == date_to_value1 and item.id != rec.id:
raise exceptions.Warning(
_('Sorry You Have Used All Your Permission In This Day you have one permission per a Day'))
@ -278,16 +290,17 @@ class HrPersonalPermission(models.Model):
clause_3 = ['&', ('date_from', '<=', date_from), ('date_to', '>=', date_to)]
return clause_1, clause_2, clause_3
@api.constrains('date_from', 'date_to')
@api.constrains('date_from', 'date_to', 'permission_type_id')
def _get_date_constrains(self):
for item in self:
item.check_holiday_mission()
current_month = (datetime.utcnow() + timedelta(hours=3)).date().month
current_year = (datetime.utcnow() + timedelta(hours=3)).date().year
month_len = monthrange(current_year, current_month)[1]
number_of_per = item.employee_id.contract_id.working_hours.permission_number
number_of_durations = item.employee_id.contract_id.working_hours.permission_hours
this_month_permission = self.search([('employee_id', '=', item.employee_id.id), ('state','not in', ('draft','refused')),
number_of_per = item.permission_type_id.monthly_hours
number_of_durations = item.permission_type_id.daily_hours
this_month_permission = self.search([('employee_id', '=', item.employee_id.id), ('permission_type_id', '=', item.permission_type_id.id),
('state','not in', ('draft','refused')),
('date_from', '>=', time.strftime('%Y-{0}-1'.format(current_month))),
('date_to', '<=',
time.strftime('%Y-{0}-{1}'.format(current_month, month_len)))])
@ -300,6 +313,7 @@ class HrPersonalPermission(models.Model):
date_to = current_date.strftime('%Y-{0}-31'.format(current_month))
employee_permissions = self.search([
('employee_id', '=', item.employee_id.id),
('permission_type_id', '=', item.permission_type_id.id),
#('state', '=', 'approve'),
('state','not in', ('draft','refused') ),
('date_from', '>=', date_from),
@ -333,7 +347,7 @@ class HrPersonalPermission(models.Model):
DEFAULT_SERVER_DATETIME_FORMAT).date()
date_to_value = datetime.strptime(str(item.date_to), DEFAULT_SERVER_DATETIME_FORMAT).date()
if permission_date == date_to_value:
if permission_date == date_to_value and item.id != employee_permission.id:
raise exceptions.Warning(
_('Sorry You Have Used All Your Permission In This Day you have one permission per a Day'))
else:
@ -364,7 +378,7 @@ class HrPersonalPermission(models.Model):
def direct_manager(self):
for rec in self:
approve_by = rec.sudo().employee_id.resource_calendar_id.approval_by
approve_by = rec.sudo().permission_type_id.approval_by
manager = rec.sudo().employee_id.parent_id
hr_manager = rec.sudo().employee_id.company_id.hr_manager_id
if manager:

View File

@ -0,0 +1,22 @@
from odoo import models, fields, api, _
class HrPersonalPermissionType(models.Model):
_name = 'hr.personal.permission.type'
_order = 'sequence asc'
name = fields.Char(required=True)
sequence = fields.Integer(readonly=True)
daily_hours = fields.Float()
monthly_hours = fields.Float()
approval_by = fields.Selection(
[('direct_manager', 'Direct Manager'), ('hr_manager', 'HR Manager')],
default='direct_manager',
required=True
)
active = fields.Boolean(default=True)
_sql_constraints = [
('uniq_name', 'UNIQUE(name)', _('Name should be unique!'))
]

View File

@ -8,6 +8,7 @@ access_house_allowance_advance_line,access_house_allowance_advance_line,model_ho
access_hr_clearance_form,access_hr_clearance_form,model_hr_clearance_form,base.group_user,1,1,1,1
access_hr_clearance_form_division,access_hr_clearance_form_division,model_hr_clearance_form,hr_base.group_division_manager,1,1,1,1
access_hr_personal_permission,access_hr_personal_permission,model_hr_personal_permission,base.group_user,1,1,1,1
access_hr_personal_permission_type,access_hr_personal_permission_type,model_hr_personal_permission_type,base.group_user,1,1,1,1
access_hr_job_emp,hr.job: Employee,hr.model_hr_job,base.group_user,1,1,1,0
access_employee_department_jobs_emp,employee_department_jobs_emp,model_employee_department_jobs,base.group_user,1,0,0,0
access_employee_department_jobs_hr,employee_department_jobs_hr,model_employee_department_jobs,hr.group_hr_user,1,1,1,1

1 id name model_id:id group_id/id perm_read perm_write perm_create perm_unlink
8 access_hr_clearance_form access_hr_clearance_form model_hr_clearance_form base.group_user 1 1 1 1
9 access_hr_clearance_form_division access_hr_clearance_form_division model_hr_clearance_form hr_base.group_division_manager 1 1 1 1
10 access_hr_personal_permission access_hr_personal_permission model_hr_personal_permission base.group_user 1 1 1 1
11 access_hr_personal_permission_type access_hr_personal_permission_type model_hr_personal_permission_type base.group_user 1 1 1 1
12 access_hr_job_emp hr.job: Employee hr.model_hr_job base.group_user 1 1 1 0
13 access_employee_department_jobs_emp employee_department_jobs_emp model_employee_department_jobs base.group_user 1 0 0 0
14 access_employee_department_jobs_hr employee_department_jobs_hr model_employee_department_jobs hr.group_hr_user 1 1 1 1

View File

@ -21,7 +21,7 @@
<menuitem name="Employee Clearance Form" id="employee_clearance_form"
parent="employee_request_menu_item" action="employee_clearance_form_action" sequence="3"/>
<menuitem name="Personal Permissions" id="employee_personal_permission_menu_item"
<menuitem name="Permissions" id="employee_personal_permission_menu_item"
parent="employee_request_menu_item"
action="employee_personal_permission_action" sequence="3"/>
@ -33,7 +33,11 @@
<!--Employee Other Request -->
<menuitem name="Employee Other Request" id="employee_other_request_menu_item"
parent="employee_request_menu_item" action="employee_other_request_action" sequence="5"/>
<menuitem
id="menu_view_permission_types"
action="action_permission_types"
parent="hr.hr_menu_configuration"/>
</data>
</odoo>

View File

@ -46,6 +46,7 @@
<sheet>
<group>
<group string="Permission Info">
<field name="permission_type_id" options="{'no_create': True, 'no_open': True, 'no_create_edit': True}" />
<field name="date" string="Date Request"
attrs="{'readonly':[('state','!=','draft')],'required':1}"/>
@ -127,6 +128,7 @@
<!--field name="date" string="Date Request"/-->
<field name="employee_no" string="Employee Number"/>
<field name="employee_id" string="Employee"/>
<field name="permission_type_id" />
<field name="date_from" string="Date From"/>
<field name="date_to" string="Date To"/>
<field name="duration" string="Duration" widget="float_time"/>
@ -146,9 +148,11 @@
<search>
<field name="employee_id"/>
<field name="employee_no"/>
<field name="permission_type_id"/>
<field name="department_id" />
<group expand="0" string="Group By">
<filter name="group_employee" string="Employee" domain="[]" context="{'group_by': 'employee_id'}"/>
<filter name="group_permission_type" string="Permission Type" domain="[]" context="{'group_by': 'permission_type_id'}"/>
<filter name="group_department" string="Department" domain="[]" context="{'group_by': 'department_id'}"/>
<filter name="group_branch" string="Branch" domain="[]" context="{'group_by': 'is_branch'}"/>
<filter name="group_state" string="State" domain="[]" context="{'group_by': 'state'}"/>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="hr_personal_permission_type_view_form" model="ir.ui.view">
<field name="name">hr.personal.permission.type.view.form</field>
<field name="model">hr.personal.permission.type</field>
<field name="arch" type="xml">
<form string="Permission Type">
<sheet>
<field name="active" invisible="1" />
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" />
</h1>
</div>
<group>
<group>
<field name="daily_hours" widget="float_time" />
<field name="monthly_hours" widget="float_time" />
</group>
<group>
<field name="approval_by" />
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="hr_personal_permission_type_view_tree" model="ir.ui.view">
<field name="name">hr.personal.permission.type.view.tree</field>
<field name="model">hr.personal.permission.type</field>
<field name="arch" type="xml">
<tree string="Permission Types">
<field name="active" invisible="1" />
<field name="sequence" widget="handle" />
<field name="name" />
<field name="daily_hours" widget="float_time" />
<field name="monthly_hours" widget="float_time" />
<field name="approval_by" options="{'no_create': True, 'no_open': True, 'no_create_edit': True}" />
</tree>
</field>
</record>
<record id="action_permission_types" model="ir.actions.act_window">
<field name="type">ir.actions.act_window</field>
<field name="name">Permission Types</field>
<field name="res_model">hr.personal.permission.type</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import models

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
###################################################################################
{
'name': 'Appraisal KPI',
'version': '11.0.1.0.0',
'category': 'HR-Odex',
'summary': 'Manage Appraisal KPI',
'description': """
Helps you to manage Appraisal of your company's staff.
""",
'author': 'Expert Co. Ltd.',
'company': 'Exp-co-ltd',
'maintainer': 'Cybrosys Techno Solutions',
'website': 'http://exp-sa.com',
'depends': [
'exp_hr_appraisal', 'base','kpi_scorecard', 'hr','kpi_scorecard', 'account', 'exp_hr_payroll', 'mail', 'hr_base', 'hr_contract', 'hr_contract_custom'
],
'data': [
'security/group.xml',
'security/ir.model.access.csv',
'views/kpi_category.xml',
'views/kpi_item.xml',
'views/kpi_period.xml',
'views/kpi_skills.xml',
'views/skill_appraisal.xml',
'views/years_employee_goals.xml',
'views/employee_performance_evaluation.xml',
'views/appraisal_percentage.xml',
'views/employee_apprisal.xml',
],
'installable': True,
'auto_install': False,
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
from . import kpi_item
from . import kpi_period
from . import kpi_skill
from . import skill_apprisal
from . import years_employee_goals
from . import employee_performance_evaluation
from . import appraisal_percentage
from . import employee_apprisal

View File

@ -0,0 +1,23 @@
from odoo import fields, models, api,_
from odoo.exceptions import ValidationError
class AppraisalPercentage(models.Model):
_name = 'job.class.apprisal'
_description = 'Appraisal Percentage'
name = fields.Char(string='Name')
percentage_kpi = fields.Float(string="Percentage of indicator Appraisal%",)
percentage_skills = fields.Float(string="Percentage of Skills Appraisal%",)
job_ids = fields.Many2many(
comodel_name='hr.job',
string='Jobs')
# Constraint to ensure total percentage is 100
@api.constrains('percentage_kpi', 'percentage_skills')
def _check_percentage_total(self):
for record in self:
total_percentage = record.percentage_kpi + record.percentage_skills
if total_percentage != 1:
raise ValidationError(_("Total percentage should be 100."))
if self.job_ids:
for rec in self.job_ids:
rec.appraisal_percentages_id = self.id

View File

@ -0,0 +1,162 @@
from odoo import models, fields,_,api,exceptions
class EmployeeApprisal(models.Model):
_inherit = 'hr.group.employee.appraisal'
year_id = fields.Many2one(comodel_name='kpi.period',string='Year',required=True)
appraisal_ids = fields.One2many('hr.employee.appraisal', 'employee_appraisal2')
def gen_appraisal(self):
for item in self:
if item.employee_ids:
appraisal_lines_list = []
# Fill employee appraisal
for element in item.employee_ids:
standard_appraisal_list, manager_appraisal_list = [], []
year_goal_obj = self.env['years.employee.goals'].search([('employee_id','=',element.id),('year_id','=',self.year_id.id)])
print('year = ',year_goal_obj)
goal_ids = year_goal_obj.ids if year_goal_obj else []
appraisal_line = {
'employee_id': element.id,
'manager_id': item.manager_id.id,
'year_id': item.year_id.id,
'department_id': item.department_id.id,
'job_id': element.job_id.id,
'appraisal_date': item.date,
'goal_ids': [(6, 0, goal_ids)],
}
line_id = self.env['hr.employee.appraisal'].create(appraisal_line)
line_id.compute_apprisal()
appraisal_lines_list.append(line_id.id)
item.appraisal_ids = self.env['hr.employee.appraisal'].browse(appraisal_lines_list)
else:
raise exceptions.Warning(_('Please select at least one employee to make appraisal.'))
item.state = 'gen_appraisal'
def draft(self):
print('draft ..............')
# Delete all appraisals when re-draft
if self.appraisal_ids:
print('if appr line.............')
for line in self.appraisal_ids:
print('for..................')
if line.state == 'draft':
print('state...........')
line.unlink()
self.state = 'draft'
elif line.state == 'closed':
line.state = 'state_done'
self.state = 'start_appraisal'
elif line.state == 'state_done':
self.state = 'start_appraisal'
# Call the original draft method using super()
class EmployeeApprisal(models.Model):
_inherit = 'hr.employee.appraisal'
employee_appraisal2 = fields.Many2one('hr.group.employee.appraisal') # Inverse field
employee_id = fields.Many2one('hr.employee', string='Employee',tracking=True,required=True)
manager_id = fields.Many2one('hr.employee', string='Manager',readonly=False,tracking=True,required=True,default=lambda item: item.get_user_id())
year_id = fields.Many2one(comodel_name='kpi.period',string='Year',required=True)
period_goals_id = fields.Many2one('kpi.period.notes',force_save=1,string='Period',tracking=True,)
department_id = fields.Many2one('hr.department',required=True,readonly=False,store=True,compute='compute_depart_job', tracking=True,string='Department')
job_id = fields.Many2one('hr.job',force_save=1,readonly=True,store=True, string='Job Title',related='employee_id.job_id',tracking=True,)
goals_mark = fields.Float(store=True,string='Goals Apprisal Mark',readonly=True,tracking=True)
skill_mark = fields.Float(store=True,string='Skills Apprisal Mark',readonly=True,tracking=True)
total_score = fields.Float(string='Total Mark',store=True,readonly=True,compute='compute_total_score',tracking=True)
apprisal_result = fields.Many2one('appraisal.result',string='Apprisal Result',store=True,tracking=True)
notes= fields.Text(string='Notes',required=False)
goal_ids = fields.One2many('years.employee.goals', 'employee_apprisal_id', string='Goals')
skill_ids = fields.One2many('skill.item.employee.table', 'employee_apprisal_id', string='Skills')
@api.constrains('employee_id', 'year_id')
def check_unique_employee_year_period_goals(self):
for record in self:
if self.search_count([
('employee_id', '=', record.employee_id.id),
('year_id', '=', record.year_id.id),
('id', '!=', record.id),
]) > 0:
raise exceptions.ValidationError(_("Employee Apprisal must be unique per Employee, Year, and Period!"))
@api.depends('skill_mark','goals_mark',)
def compute_total_score(self):
appraisal_result_list = []
for rec in self:
if rec.skill_mark and rec.goals_mark and rec.job_id.appraisal_percentages_id.percentage_kpi>0.0 and rec.job_id.appraisal_percentages_id.percentage_skills>0.0:
skill_mark_precentage = rec.skill_mark*rec.job_id.appraisal_percentages_id.percentage_skills
goal_mark_precentage = rec.goals_mark*rec.job_id.appraisal_percentages_id.percentage_kpi
rec.total_score = (skill_mark_precentage+goal_mark_precentage)
appraisal_result = self.env['appraisal.result'].search([
('result_from', '<', rec.total_score),
('result_to', '>=', rec.total_score)])
if rec.total_score and len(appraisal_result) > 1:
for line in appraisal_result:
appraisal_result_list.append(line.name)
raise exceptions.Warning(
_('Please check appraisal result configuration , there is more than result for '
'percentage %s are %s ') % (
round(rec.total_score, 2), appraisal_result_list))
else:
rec.appraisal_result = appraisal_result.id
def get_user_id(self):
employee_id = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
if employee_id:
return employee_id.id
else:
return False
@api.depends('employee_id')
def compute_depart_job(self):
for rec in self:
if rec.employee_id:
rec.department_id = rec.employee_id.department_id.id
def compute_apprisal(self):
year_goal_obj = self.env['years.employee.goals'].search([('employee_id','=',self.employee_id.id),('year_id','=',self.year_id.id)])
if year_goal_obj:
print('if goal...........')
self.goal_ids = year_goal_obj.ids
#
sum2 = 0
for rec in self.goal_ids:
sum2 = sum2+ ((rec.weight*int(rec.choiec))/100)
self.goals_mark = sum2
#
item_lines=[(5,0,0)]
skill_apprisal = self.env['skill.appraisal'].search([('employee_id','=',self.employee_id.id),('year_id','=',self.year_id.id),('job_id','=',self.job_id.id)])
dic_item = {}
print('s a = ',skill_apprisal)
for obj in skill_apprisal:
for rec in obj.items_ids:
if rec.mark and rec.item_id:
if rec.item_id.name in dic_item:
dic_item[rec.item_id.name].append(rec.mark)
else:
dic_item.update({rec.item_id.name:[rec.mark]})
print('dic_item = ',dic_item)
averages = {}
for key, values in dic_item.items():
# Convert values to integers and calculate sum
total = sum(int(value) for value in values)
# Calculate average
avg = total / len(values)
# Store the average in the dictionary
averages[key] = avg
if self.job_id:
for line in self.job_id.item_job_ids:
line_item = {'item_id':line.item_id.id,'name':line.name,'level':line.level,}
if line.item_id.name in averages:
line_item.update({'mark_avg':averages[line.item_id.name]})
item_lines.append((0,0,line_item))
self.skill_ids = item_lines
# Calculate the average of averages
if len(averages)!=0:
average_of_averages = sum(averages.values()) / len(averages)
self.skill_mark = average_of_averages

View File

@ -0,0 +1,149 @@
from odoo import fields, models, exceptions, api, _
from odoo.exceptions import UserError, ValidationError
from lxml import etree
import json
class EmployeePerformanceEvaluation(models.Model):
_name = 'employee.performance.evaluation'
_rec_name = 'employee_id'
_inherit = ['mail.thread']
_description = "Employee performance evaluation"
recommendations = fields.Text(string='Recommendations', tracking=True, required=False)
total = fields.Float(string='Total Mark', readonly=True, store=True, tracking=True, )
mark_apprisal = fields.Float(string='Mark Apprisal', readonly=False, store=True, tracking=True,
compute='total_mark')
date_apprisal = fields.Date(default=lambda self: fields.Date.today(), string='Apprisal Date', tracking=True, )
employee_id = fields.Many2one('hr.employee', string='Employee', tracking=True, required=True)
manager_id = fields.Many2one('hr.employee', string='Employee m', readonly=False, tracking=True, required=False,
default=lambda item: item.get_user_id())
year_id = fields.Many2one(comodel_name='kpi.period', string='Year')
period_goals_id = fields.Many2one('kpi.period.notes', force_save=1, string='Period', tracking=True, )
department_id = fields.Many2one('hr.department', readonly=False, store=True, compute='compute_depart_job',
tracking=True, string='Department')
job_id = fields.Many2one('hr.job', force_save=1, readonly=True, store=True, string='Job Title',
related='employee_id.job_id', tracking=True, )
state = fields.Selection([
('draft', 'Draft'), ('dir_manager', 'Wait Employee Accept'),
('wait_dir_manager', 'Wait Manager Accept'),
('wait_hr_manager', 'Wait HR Manager Accept'),
('approve', 'Accept'),
('refuse', 'Refused')
], string='State', tracking=True, default='draft')
emp_goal_ids = fields.One2many(comodel_name='period.goals', inverse_name='employee_eval_id',
string='Employee Goals', copy=True)
@api.constrains('employee_id', 'year_id', 'period_goals_id')
def check_unique_employee_year_period_goals(self):
for record in self:
if self.search_count([
('employee_id', '=', record.employee_id.id),
('year_id', '=', record.year_id.id),
('period_goals_id', '=', record.period_goals_id.id),
('id', '!=', record.id),
]) > 0:
raise exceptions.ValidationError(
_("Employee Goals Apprisal must be unique per Employee, Year, and Period!"))
def get_user_id(self):
employee_id = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
if employee_id:
return employee_id.id
else:
return False
@api.depends('employee_id')
def compute_depart_job(self):
for rec in self:
if rec.employee_id:
rec.department_id = rec.employee_id.department_id.id
@api.model
def fields_view_get(self, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(EmployeePerformanceEvaluation, self).fields_view_get(view_id=view_id, view_type=view_type,
toolbar=toolbar,
submenu=submenu)
doc = etree.XML(res['arch'])
emp_group = self.env.ref('exp_hr_appraisal.group_appraisal_employee').id
user_group = self.env.ref('exp_hr_appraisal.group_appraisal_user').id
manager_group = self.env.ref('exp_hr_appraisal.group_appraisal_manager').id
current_user_gids = self.env.user.groups_id.mapped('id')
if ((emp_group in current_user_gids) and (user_group not in current_user_gids) and (
manager_group not in current_user_gids)):
if view_type == 'tree' or view_type == 'form':
print('if node1.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('if node.....')
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
for node in doc.xpath("//form"):
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
res['arch'] = etree.tostring(doc)
elif ((user_group in current_user_gids or manager_group in current_user_gids)):
if view_type == 'tree' or view_type == 'form':
print('if node2.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
elif (
user_group in current_user_gids and manager_group in current_user_gids and emp_group in current_user_gids):
if view_type == 'tree' or view_type == 'form':
print('if node3.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
return res
def send(self):
self.state = 'wait_dir_manager'
def reset_draft(self):
self.state = 'draft'
def action_approval(self):
if self.state == 'dir_manager':
self.state = 'wait_dir_manager'
elif self.state == 'wait_dir_manager':
self.state = 'wait_hr_manager'
else:
self.state = 'approve'
def action_refuse(self):
self.state = 'refuse'
def onchange_emp_goal_ids(self):
goals_lines = [(5, 0, 0)]
sum = 0
period_goal_obj = self.env['period.goals'].search(
[('period_goals_id', '=', self.period_goals_id.id), ('employee_id', '=', self.employee_id.id),
('year_id', '=', self.year_id.id)])
self.emp_goal_ids = period_goal_obj.ids
for rec in self.emp_goal_ids:
sum = sum + ((rec.weight * rec.mark_evaluation) / 100)
self.mark_apprisal = sum
def unlink(self):
for rec in self:
if rec.state != 'draft':
raise ValidationError(_("You can't delete a Goal apprisal not in Draft State , archive it instead."))
return super().unlink()

View File

@ -0,0 +1,150 @@
from odoo import fields, models, api,_
from lxml import etree
import json
from odoo.exceptions import MissingError, UserError, ValidationError, AccessError
class KPICategory(models.Model):
_inherit = 'kpi.category'
@api.model
def fields_view_get(self, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(KPICategory, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=submenu)
doc = etree.XML(res['arch'])
emp_group = self.env.ref('exp_hr_appraisal.group_appraisal_employee').id
user_group = self.env.ref('exp_hr_appraisal.group_appraisal_user').id
manager_group = self.env.ref('exp_hr_appraisal.group_appraisal_manager').id
current_user_gids = self.env.user.groups_id.mapped('id')
if ((emp_group in current_user_gids) and (user_group not in current_user_gids )and(manager_group not in current_user_gids)):
if view_type=='tree' or view_type=='form':
print('if node1.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('if node.....')
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
for node in doc.xpath("//form"):
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
res['arch'] = etree.tostring(doc)
elif ((user_group in current_user_gids or manager_group in current_user_gids)):
if view_type=='tree' or view_type=='form':
print('if node2.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
elif (user_group in current_user_gids and manager_group in current_user_gids and emp_group in current_user_gids):
if view_type=='tree' or view_type=='form':
print('if node3.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
return res
class KPIitem(models.Model):
_inherit = 'kpi.item'
department_item_id = fields.Many2one(comodel_name='hr.department',string='Department')
responsible_item_id = fields.Many2one(comodel_name='hr.employee',string='Responsible')
mark_ids = fields.One2many(comodel_name='mark.mark',inverse_name='kip_id')
method_of_calculate = fields.Selection(
string='Method Of Calculate',
selection=[('accumulative', 'Accumulative'),
('avrerage', 'Average'),('undefined', 'Undefined'),],
required=False,default='accumulative')
@api.model
def fields_view_get(self, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(KPIitem, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=submenu)
doc = etree.XML(res['arch'])
emp_group = self.env.ref('exp_hr_appraisal.group_appraisal_employee').id
user_group = self.env.ref('exp_hr_appraisal.group_appraisal_user').id
manager_group = self.env.ref('exp_hr_appraisal.group_appraisal_manager').id
current_user_gids = self.env.user.groups_id.mapped('id')
if ((emp_group in current_user_gids) and (user_group not in current_user_gids )and(manager_group not in current_user_gids)):
if view_type=='tree' or view_type=='form':
print('if node1.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('if node.....')
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
for node in doc.xpath("//form"):
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
res['arch'] = etree.tostring(doc)
elif ((user_group in current_user_gids or manager_group in current_user_gids)):
if view_type=='tree' or view_type=='form':
print('if node2.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
elif (user_group in current_user_gids and manager_group in current_user_gids and emp_group in current_user_gids):
if view_type=='tree' or view_type=='form':
print('if node3.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
return res
@api.onchange('department_item_id')
def onchange_responsible(self):
domain = []
if self.department_item_id:
# Define your dynamic domain based on field1's value
domain = [('department_id', '=', self.department_item_id.id)]
return {'domain': {'responsible_item_id': domain}}
class Marks(models.Model):
_name = 'mark.mark'
choiec = fields.Selection(string='Choiec',selection=[('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'),('5','5'),])
target = fields.Float(string='From(Done)',)
to = fields.Float(string='To(Target)',)
kip_id = fields.Many2one(comodel_name='kpi.item',string='Kip_id')
@api.constrains('target', 'to', 'kip_id')
def _check_target_to_values(self):
for record in self:
if record.to <= record.target:
raise ValidationError(_('The To value must be greater than the From value.'))
# Get previous marks for the same KPI sorted by target
# previous_marks = self.env['mark.mark'].search([('kip_id', '=', record.kip_id.id), ('id', '!=', record.id)], order='target')
# for prev_mark in previous_marks:
# if record.target <= prev_mark.to:
# raise ValidationError(_('The From value must be greater than the previous To value.'))

View File

@ -0,0 +1,64 @@
from odoo import fields, models, api,_
from odoo.exceptions import ValidationError
from odoo import models, api, exceptions
from datetime import timedelta
class KPIPeriod(models.Model):
_inherit = 'kpi.period'
kpi_periods_ids = fields.One2many(
comodel_name='kpi.period.notes',
inverse_name='kpi_period_id',
ondelete='cascade') # Add this line to enable cascade deletion
kpi_goals_periods_ids = fields.One2many(
comodel_name='kpi.period.notes',
inverse_name='kpi_goal_period_id',
ondelete='cascade' ) # Add this line to enable cascade deletion
class KIPSkills (models.Model):
_name = 'kpi.period.notes'
name = fields.Char(string='Name',)
sequence = fields.Char(string='Sequence',)
date_start_k = fields.Date(string='Star Date',)
date_end_k = fields.Date(string='End Date',)
kpi_period_id = fields.Many2one(comodel_name='kpi.period',ondelete='cascade')
kpi_goal_period_id = fields.Many2one(comodel_name='kpi.period',ondelete='cascade')
def create_apprisal_goals_employee(self):
employee_objs = self.env['hr.employee'].search([('state','=','open')])
employee_id = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
for item in self:
# Fill employee appraisal
for element in employee_objs:
appraisal_line = {
'employee_id': element.id,
'year_id': item.kpi_goal_period_id.id,
'department_id': element.department_id.id,
'job_id': element.job_id.id,
'manager_id': employee_id.id,
'date_apprisal': fields.Date.today(),
'period_goals_id': item.id,
}
line_id = self.env['employee.performance.evaluation'].create(appraisal_line)
line_id.onchange_emp_goal_ids()
@api.constrains('date_start_k','kpi_goal_period_id','date_end_k')
def _check_period_overlap(self):
print('in constriant..2222.........')
for record in self:
if record.kpi_goal_period_id:
periods = record.kpi_goal_period_id.kpi_goals_periods_ids.sorted(key=lambda r: r.date_start_k)
for i in range(1, len(periods)):
if periods[i-1].date_end_k >= periods[i].date_start_k:
raise ValidationError(_("Overlap detected between periods!"))
@api.constrains('date_start_k','kpi_period_id','date_end_k')
def _check_period_overlap2(self):
print('in constriant...........')
for record in self:
if record.kpi_period_id:
periods = record.kpi_period_id.kpi_periods_ids.sorted(key=lambda r: r.date_start_k)
for i in range(1, len(periods)):
if periods[i-1].date_end_k >= periods[i].date_start_k:
raise ValidationError(_("Overlap detected between periods!"))

View File

@ -0,0 +1,61 @@
from odoo import fields, models, api
class Skill(models.Model):
_name = 'skill.skill'
_inherit = ['mail.thread']
name = fields.Char(string='Name', required=True,tracking=True,)
description = fields.Text(string='Description',tracking=True,)
items_ids = fields.One2many('skill.item', 'skill_id', string='Items',tracking=True,)
class SkillItems(models.Model):
_name = 'skill.item'
skill_id = fields.Many2one('skill.skill', string='Skill',ondelete='cascade')
skill_appraisal_id = fields.Many2one(comodel_name='skill.appraisal')
name = fields.Char(string='Description')
level = fields.Selection([('beginner', '1'),('intermediate', '2'),('advanced', '3')],string='Level', default='beginner')
mark = fields.Selection([('1', '1'),('2', '2'),('3', '3'),('4', '4'),('5', '5')],string='Mark',Ccopy=False)
mark_avg = fields.Float(string='Mark',Ccopy=False)
item_id = fields.Many2one(comodel_name='item.item',string='Item')
display_type = fields.Selection([
('line_section', "Section"),
('line_note', "Note")],default=False, help="Technical field for UX purpose.")
employee_apprisal_id = fields.Many2one(
comodel_name='hr.employee.appraisal')
sequence = fields.Integer(string='Sequence', default=10)
class SkillItems(models.Model):
_name = 'skill.item.table'
skill_id = fields.Many2one('skill.skill', string='Skill')
skill_appraisal_id = fields.Many2one(comodel_name='skill.appraisal',ondelete='cascade')
name = fields.Char(string='Description')
level = fields.Selection([('beginner', '1'),('intermediate', '2'),('advanced', '3')],string='Level', default='beginner')
mark = fields.Selection([('1', '1'),('2', '2'),('3', '3'),('4', '4'),('5', '5')],string='Mark',Ccopy=False)
mark_avg = fields.Float(string='Mark',Ccopy=False)
item_id = fields.Many2one(comodel_name='item.item',string='Item')
employee_apprisal_id = fields.Many2one(
comodel_name='hr.employee.appraisal')
class SkillItems(models.Model):
_name = 'skill.item.employee.table'
skill_id = fields.Many2one('skill.skill', string='Skill')
skill_appraisal_id = fields.Many2one(comodel_name='skill.appraisal',ondelete='cascade')
name = fields.Char(string='Description')
level = fields.Selection([('beginner', '1'),('intermediate', '2'),('advanced', '3')],string='Level', default='beginner')
mark = fields.Selection([('1', '1'),('2', '2'),('3', '3'),('4', '4'),('5', '5')],string='Mark',Ccopy=False)
mark_avg = fields.Float(string='Mark',Ccopy=False)
item_id = fields.Many2one(comodel_name='item.item',string='Item')
employee_apprisal_id = fields.Many2one(
comodel_name='hr.employee.appraisal')
class SkillItem(models.Model):
_name = 'item.item'
name = fields.Char(string='Name')
class SkillJob(models.Model):
_inherit = 'hr.job'
item_job_ids = fields.Many2many('skill.item', 'merge_item_skill1_rel', 'merge1_id', 'item1_id', string='Skills')
# appraisal_percentage_id = fields.Many2one(comodel_name='job.class.apprisal',string='Appraisal Percentage')
appraisal_percentages_id = fields.Many2one(comodel_name='job.class.apprisal',string='Appraisal Percentage')

View File

@ -0,0 +1,141 @@
from odoo import fields, models,exceptions, api,_
from odoo.exceptions import UserError,ValidationError
from lxml import etree
import json
class SkillAppraisal(models.Model):
_name = 'skill.appraisal'
_inherit = ['mail.thread']
_rec_name = 'employee_id'
_description = 'Skill Appraisal'
name= fields.Char(string='Name',tracking=True,)
recommendations= fields.Text(string='Recommendations',tracking=True,required=False)
date_apprisal = fields.Date(default=lambda self: fields.Date.today(),string='Apprisal Date',tracking=True,)
employee_id = fields.Many2one('hr.employee', string='Employee',tracking=True,required=True)
manager_id = fields.Many2one('hr.employee', string='Manager',readonly=False,tracking=True,required=True,default=lambda item: item.get_user_id())
period = fields.Many2one('kpi.period.notes',string='Period',tracking=True,)
department_id = fields.Many2one('hr.department',readonly=True,store=True,compute='compute_depart_job', tracking=True,string='Department')
job_id = fields.Many2one('hr.job',readonly=False,store=True, string='Job Title',tracking=True,)
year_id = fields.Many2one(comodel_name='kpi.period',string='Year')
@api.constrains('employee_id', 'year_id', 'period')
def check_unique_employee_year_period_skills(self):
for record in self:
if self.search_count([
('employee_id', '=', record.employee_id.id),
('year_id', '=', record.year_id.id),
('period', '=', record.period.id),
('id', '!=', record.id),
]) > 0:
raise exceptions.ValidationError(_("Employee Skill Apprisal must be unique per Employee, Year, and Period!"))
state = fields.Selection([
('draft', 'Draft'),('dir_manager', 'Wait Employee Accept'),
('wait_dir_manager', 'Wait Manager Accept'),
('wait_hr_manager', 'Wait HR Manager Accept'),
('approve', 'Accept'),
('refuse', 'Refused')
], string='State',tracking=True,default='draft')
avarage = fields.Float(string='Result',readonly=True,store=True,tracking=True,compute='calc_avg')
items_ids = fields.One2many(comodel_name='skill.item.table',inverse_name='skill_appraisal_id',string='Items',copy=True)
@api.model
def fields_view_get(self, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(SkillAppraisal, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=submenu)
doc = etree.XML(res['arch'])
emp_group = self.env.ref('exp_hr_appraisal.group_appraisal_employee').id
user_group = self.env.ref('exp_hr_appraisal.group_appraisal_user').id
manager_group = self.env.ref('exp_hr_appraisal.group_appraisal_manager').id
current_user_gids = self.env.user.groups_id.mapped('id')
if ((emp_group in current_user_gids) and (user_group not in current_user_gids )and(manager_group not in current_user_gids)):
if view_type=='tree' or view_type=='form':
print('if node1.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('if node.....')
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
for node in doc.xpath("//form"):
node.set('create', 'false')
node.set('delete', 'false')
node.set('edit', 'false')
res['arch'] = etree.tostring(doc)
elif ((user_group in current_user_gids or manager_group in current_user_gids)):
if view_type=='tree' or view_type=='form':
print('if node2.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
elif (user_group in current_user_gids and manager_group in current_user_gids and emp_group in current_user_gids):
if view_type=='tree' or view_type=='form':
print('if node3.....')
# if view_type == 'tree':
for node in doc.xpath("//tree"):
print('for..node')
node.set('create', 'true')
node.set('edit', 'true')
for node in doc.xpath("//form"):
node.set('create', 'true')
node.set('edit', 'true')
res['arch'] = etree.tostring(doc)
return res
def get_user_id(self):
employee_id = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
if employee_id:
return employee_id.id
else:
return False
@api.depends('employee_id')
def compute_depart_job(self):
for rec in self:
if rec.employee_id:
rec.department_id = rec.employee_id.department_id.id
rec.job_id = rec.employee_id.job_id.id
@api.depends('items_ids.mark')
def calc_avg(self):
sum = 0
for rec in self.items_ids:
if rec.mark and len(self.items_ids)!=0:
sum = sum+int(rec.mark)
self.avarage = sum/len(self.items_ids)
def send(self):
self.state = 'dir_manager'
def reset_draft(self):
self.state = 'draft'
def action_approval(self):
if self.state=='dir_manager':
self.state='wait_dir_manager'
elif self.state=='wait_dir_manager':
self.state='wait_hr_manager'
else:
self.state='approve'
def action_refuse(self):
self.state = 'refuse'
@api.onchange('job_id','employee_id')
def onchange_emp(self):
item_lines=[(5,0,0)]
for line in self.job_id.item_job_ids:
line_item = {'item_id':line.item_id.id,'name':line.name,'level':line.level}
item_lines.append((0,0,line_item))
self.items_ids = item_lines
def unlink(self):
for rec in self:
if rec.state != 'draft':
raise ValidationError(_("You can't delete a Skill apprisal not in Draft State , archive it instead."))
return super().unlink()

View File

@ -0,0 +1,220 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, api,exceptions,_
class Period(models.Model):
_name = 'period.goals'
period_goals_id = fields.Many2one('kpi.period.notes', domain=[('kpi_period_id','=',False)], string='Period Of Goals', tracking=True)
employee_goals_id = fields.Many2one('years.employee.goals')
target = fields.Float(string='Target', store=True)
done = fields.Float(string='Done')
kpi_id = fields.Many2one(comodel_name='kpi.item', string='KPI', related='employee_goals_id.kpi_id')
employee_eval_id = fields.Many2one(comodel_name='employee.performance.evaluation', string='KPI')
weight = fields.Float(string='Weight', related='employee_goals_id.weight')
mark_evaluation = fields.Integer(string='Evaluation Mark', store=True, compute='_compute_mark_evaluation')
year_id = fields.Many2one(comodel_name='kpi.period', related='employee_goals_id.year_id')
employee_id = fields.Many2one(comodel_name='hr.employee', related='employee_goals_id.employee_id')
@api.depends('done', 'target', 'kpi_id')
def _compute_mark_evaluation(self):
sum = 0
for record in self:
if record.done!=0.0 and record.target!=0.0 and record.kpi_id:
done_percentage = (record.done / record.target) * 100
marks = self.env['mark.mark'].search([('kip_id', '=', record.kpi_id.id)])
if marks:
# Finding the closest mark where the done_percentage fits into the target-to range
closest_mark = min(
marks,
key=lambda x: abs(done_percentage - ((x.target + x.to) / 2))
)
if closest_mark.target <= done_percentage <= closest_mark.to:
record.mark_evaluation = int(closest_mark.choiec)
closest_mark = None
for mark in marks:
if mark.target <= done_percentage <= mark.to:
record.mark_evaluation = mark.choiec
break
else:
record.mark_evaluation = 0 # Or any other default value if fields are empty
sum = sum+ ((record.weight*record.mark_evaluation)/100)
record.employee_eval_id.mark_apprisal = sum
class YearEmployeeGoals(models.Model):
_name = 'years.employee.goals'
_inherit = ['mail.thread']
_description = 'years employee goals'
_rec_name = 'employee_id'
employee_id = fields.Many2one('hr.employee', string='Employee',tracking=True,required=True)
year_id = fields.Many2one(comodel_name='kpi.period',string='Year')
category_id = fields.Many2one(comodel_name='kpi.category',string='Category')
kpi_id = fields.Many2one(comodel_name='kpi.item',string='KPI',)
method_of_calculate = fields.Selection(related='kpi_id.method_of_calculate')
responsible_item_id = fields.Many2one(comodel_name='hr.employee',related='kpi_id.responsible_item_id',store=True,string='Responsible')
user_id = fields.Many2one(comodel_name='res.users',related='responsible_item_id.user_id',store=True,string='Responsible')
department_id = fields.Many2one('hr.department',readonly=True,store=True,compute='compute_depart_job', tracking=True,string='Department')
job_id = fields.Many2one('hr.job',readonly=True,store=True,compute='compute_depart_job', string='Job Title',tracking=True,)
year_target = fields.Float(string='Year Target')
weight = fields.Float(string='Weight')
goals_period_ids = fields.One2many(comodel_name='period.goals',inverse_name='employee_goals_id',string='Period',copy=False)
done = fields.Float(string='Done',store=True,compute='total_done')
state = fields.Selection([('draft', 'Draft'),('apprisal', 'Apprisal'),('close', 'Close')], string='State',tracking=True,default='draft')
choiec = fields.Integer(string='Choiec',store=True,compute='compute_choice')
employee_apprisal_id = fields.Many2one(comodel_name='hr.employee.appraisal')
first_period_traget = fields.Float(compute='_compute_first_period_traget', string='First Period Traget',
inverse='_inverse_first_period_traget')
second_period_traget = fields.Float(compute='_compute_second_period_traget', string='Second Period Traget',
inverse='_inverse_second_period_traget')
third_period_traget = fields.Float(compute='_compute_third_period_traget', string='Third Period Traget',
inverse='_inverse_third_period_traget')
fourth_period_traget = fields.Float(compute='_compute_fourth_period_traget', string='Fourth Period Traget',
inverse='_inverse_fourth_period_traget')
def _compute_first_period_traget(self):
for rec in self:
rec.first_period_traget = 0.0
first_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '1')
if first_period:
rec.first_period_traget = first_period.target
def _inverse_first_period_traget(self):
for rec in self:
first_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '1')
if first_period:
first_period.sudo().target = rec.first_period_traget
else:
if rec.year_id:
first_period = rec.year_id.kpi_goals_periods_ids.filtered(lambda period: period.sequence == '1')
if first_period:
rec.goals_period_ids = [(0, 0, {'period_goals_id':first_period.id,'target':rec.first_period_traget})]
def _compute_second_period_traget(self):
for rec in self:
rec.second_period_traget = 0.0
second_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '2')
if second_period:
rec.second_period_traget = second_period.target
def _inverse_second_period_traget(self):
for rec in self:
second_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '2')
if second_period:
second_period.sudo().target = rec.second_period_traget
else:
if rec.year_id:
second_period = rec.year_id.kpi_goals_periods_ids.filtered(lambda period: period.sequence == '2')
if second_period:
rec.goals_period_ids = [(0, 0, {'period_goals_id':second_period.id,'target':rec.second_period_traget})]
def _compute_third_period_traget(self):
for rec in self:
rec.third_period_traget = 0.0
third_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '3')
if third_period:
rec.third_period_traget = third_period.target
def _inverse_third_period_traget(self):
for rec in self:
third_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '3')
if third_period:
third_period.sudo().target = rec.third_period_traget
else:
if rec.year_id:
third_period = rec.year_id.kpi_goals_periods_ids.filtered(lambda period: period.sequence == '3')
if third_period:
rec.goals_period_ids = [(0, 0, {'period_goals_id':third_period.id,'target':rec.third_period_traget})]
def _compute_fourth_period_traget(self):
for rec in self:
rec.fourth_period_traget = 0.0
fourth_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '4')
if fourth_period:
rec.fourth_period_traget = fourth_period.target
def _inverse_fourth_period_traget(self):
for rec in self:
fourth_period = rec.goals_period_ids.filtered(lambda period: period.period_goals_id.sequence == '4')
if fourth_period:
fourth_period.sudo().target = rec.fourth_period_traget
else:
if rec.year_id:
fourth_period = rec.year_id.kpi_goals_periods_ids.filtered(lambda period: period.sequence == '4')
if fourth_period:
rec.goals_period_ids = [(0, 0, {'period_goals_id':fourth_period.id,'target':rec.fourth_period_traget})]
@api.model
def search(self, args, offset=0, limit=None, order=None, count=False):
# add domain filter to only show records related to login responsible_item_id employee
if self.env.user.has_group("exp_hr_appraisal_kpi.group_appraisal_responsabil") and not self.env.user.has_group("exp_hr_appraisal.group_appraisal_manager") and not self.env.user.has_group("exp_hr_appraisal.group_appraisal_user") :
args += [('user_id','=',self.env.user.id)]
return super (YearEmployeeGoals,self).search(args,offset,limit,order,count)
@api.depends('goals_period_ids.done','goals_period_ids.target','method_of_calculate')
def total_done(self):
for rec in self:
if rec.method_of_calculate=='accumulative':
sum=0
for record in rec.goals_period_ids:
sum = sum+record.done
rec.done = sum
elif rec.method_of_calculate=='avrerage':
sum=0
for record in rec.goals_period_ids:
sum = (sum+record.done)
rec.done = sum/len(rec.goals_period_ids)
else:
rec.done=0.0
@api.depends('goals_period_ids.done','done','goals_period_ids.target','method_of_calculate')
def compute_choice(self):
for rec in self:
choice = 0
if rec.done!=0.0 and rec.year_target!=0.0 and rec.kpi_id:
done_percentage = (rec.done / rec.year_target) * 100
marks = self.env['mark.mark'].search([('kip_id', '=', rec.kpi_id.id),('target','<=',done_percentage),('to','>=',done_percentage)],limit=1)
if marks:
choice = marks.choiec
rec.choiec = int(choice)
def apprisal(self):
self.state='apprisal'
def action_close(self):
self.state='close'
def action_set_to_dratt(self):
self.state='draft'
@api.constrains('employee_id', 'year_id', 'kpi_id')
def check_unique_employee_year_period_goals(self):
for record in self:
if self.search_count([
('employee_id', '=', record.employee_id.id),
('year_id', '=', record.year_id.id),
('kpi_id', '=', record.kpi_id.id),
('id', '!=', record.id),
]) > 0:
raise exceptions.ValidationError(_("Employee Goals must be unique per Employee, Year, and kpi!"))
@api.depends('employee_id')
def compute_depart_job(self):
for rec in self:
if rec.employee_id:
rec.department_id = rec.employee_id.department_id.id
rec.job_id = rec.employee_id.job_id.id
@api.onchange('year_id')
def onchange_emp(self):
goals_lines=[(5,0,0)]
if self.year_id:
for line in self.year_id.kpi_goals_periods_ids:
line_item = {'period_goals_id':line.id}
goals_lines.append((0,0,line_item))
self.goals_period_ids = goals_lines

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="apprisal_kpi_group" model="res.groups">
<field name="name">Menu apprisal hide/show</field>
</record>
<record id="group_appraisal_responsabil" model="res.groups">
<field name="name">Goals Responsible</field>
<field name="category_id" ref="exp_hr_appraisal.module_category_hr_appraisal"/>
<field name="implied_ids" eval="[(4, ref('base.group_user')),(4, ref('exp_hr_appraisal.group_appraisal_employee'))]"/>
</record>
<record id="extended_kpi_category_rule" model="ir.rule">
<field name="name">Extended KPI Category Rule</field>
<field name="model_id" ref="kpi_scorecard.model_kpi_category"/>
<field name="domain_force">[
'|',
('company_id','=', False),
('company_id', 'in', company_ids),
]
</field>
<field name="groups"
eval="[(4, ref('base.group_user')), (4, ref('exp_hr_appraisal.group_appraisal_employee')),(4, ref('exp_hr_appraisal.group_appraisal_manager')),(4, ref('exp_hr_appraisal.group_appraisal_user'))]"/>
</record>
<record id="extended_kpi_item_rule" model="ir.rule">
<field name="name">Extended KPI Category Rule</field>
<field name="model_id" ref="kpi_scorecard.model_kpi_item"/>
<field name="domain_force">[
'|',
('company_id','=', False),
('company_id', 'in', company_ids),
]
</field>
<field name="groups"
eval="[(4, ref('base.group_user')), (4, ref('exp_hr_appraisal.group_appraisal_employee')),(4, ref('exp_hr_appraisal.group_appraisal_manager')),(4, ref('exp_hr_appraisal.group_appraisal_user'))]"/>
</record>
<!--add record rule for skill apprisal,employee apprisal -->
<record id="hr_employee_appraisal_kpi_employee_rule" model="ir.rule">
<field name="name">Employee: views its Skill appraisals only</field>
<field name="model_id" ref="model_skill_appraisal"/>
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="hr_employee_appraisal_goal_kpi_employee_rule" model="ir.rule">
<field name="name">Employee: views its Goal appraisals only</field>
<field name="model_id" ref="model_employee_performance_evaluation"/>
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="hr_employee_kpi_appraisal_manager_rule" model="ir.rule">
<field name="name">Manager: views Skill appraisals of its subordinates</field>
<field name="model_id" ref="model_skill_appraisal"/>
<field name="domain_force">['|','|',('employee_id.department_id.manager_id','=',False),
('employee_id.department_id.manager_id.user_id','in', [user.id]),
('employee_id.department_id.parent_id.manager_id.user_id','in', [user.id])]
</field>
<field name="groups"
eval="[(4, ref('hr_base.group_department_manager')),(4, ref('hr_base.group_division_manager'))]"/>
</record>
<record id="hr_employee_kpi_appraisal_goals_manager_rule" model="ir.rule">
<field name="name">Manager: views Goals appraisals of its subordinates</field>
<field name="model_id" ref="model_employee_performance_evaluation"/>
<field name="domain_force">['|','|',('employee_id.department_id.manager_id','=',False),
('employee_id.department_id.manager_id.user_id','in', [user.id]),
('employee_id.department_id.parent_id.manager_id.user_id','in', [user.id])]
</field>
<field name="groups"
eval="[(4, ref('hr_base.group_department_manager')),(4, ref('hr_base.group_division_manager'))]"/>
</record>
<record id="hr_employee_skill_appraisal_all_rule" model="ir.rule">
<field name="name"> Manager: views Skills appraisals of all subordinates </field>
<field name="model_id" ref="model_employee_performance_evaluation"/>
<field name="domain_force">[(1 ,'=', 1)]</field>
<field name="groups" eval="[(4, ref('hr_base.group_executive_manager')),
(4, ref('hr_base.group_general_manager')),
(4, ref('exp_hr_appraisal.group_appraisal_manager')),
(4, ref('hr.group_hr_user'))]"/>
</record>
<record id="hr_employee_goal_appraisal_all_rule" model="ir.rule">
<field name="name"> Manager: views Goals appraisals of all subordinates </field>
<field name="model_id" ref="model_skill_appraisal"/>
<field name="domain_force">[(1 ,'=', 1)]</field>
<field name="groups" eval="[(4, ref('hr_base.group_executive_manager')),
(4, ref('hr_base.group_general_manager')),
(4, ref('exp_hr_appraisal.group_appraisal_manager')),
(4, ref('hr.group_hr_user'))]"/>
</record>
<!--#################################################################################################################################################################-->
<!-- end -->
</data>
</odoo>

View File

@ -0,0 +1,71 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mark2,access_marks2,model_mark_mark,base.group_user,1,1,1,1
access_mark3,access_marks3,model_mark_mark,exp_hr_appraisal.group_appraisal_employee,1,1,1,1
access_mark4,access_marks4,model_mark_mark,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_mark5,access_marks5,model_mark_mark,exp_hr_appraisal.group_appraisal_user,1,1,1,1
access_kpi_p7,access_kpi_ps8,model_kpi_period_notes,base.group_user,1,1,1,1
access_kpi_p7,access_kpi_ps8,model_kpi_period_notes,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_p7,access_kpi_ps8,model_kpi_period_notes,exp_hr_appraisal.group_appraisal_user,1,1,1,1
access_kpi_p7,access_kpi_ps8,model_kpi_period_notes,exp_hr_appraisal.group_appraisal_employee,1,1,1,1
access_kpi_p535,access_kpi_ps185,model_skill_skill,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_p535,access_kpi_ps185,model_skill_skill,exp_hr_appraisal.group_appraisal_user,1,1,1,1
access_kpi_p54435,access_kpi_ps18555,model_skill_item,base.group_user,1,1,1,1
access_kpi_p544355,access_kpi_ps189555,model_skill_item_table,base.group_user,1,1,1,1
access_kpi_p544385,access_kpi_ps179555,model_skill_item_employee_table,base.group_user,1,1,1,1
access_kpi_p53577,access_kpi_ps17785,model_item_item,base.group_user,1,1,1,1
access_kpi_p53577,access_kpi_ps17785,model_item_item,exp_hr_appraisal.group_appraisal_user,1,1,1,1
access_kpi_p53577,access_kpi_ps17785,model_item_item,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_p53577,access_kpi_ps17785,model_item_item,exp_hr_appraisal.group_appraisal_employee,1,1,1,1
access_kpi_p5357b7p,access_kpbi_ps17785p,model_skill_appraisal,base.group_user,1,1,1,1
access_kpi_p5357b7,access_kpbi_ps17785,model_skill_appraisal,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_p5357b7,access_kpbi_ps17785,model_skill_appraisal,exp_hr_appraisal.group_appraisal_user,1,1,1,1
access_kpi_p5357b7,access_kpbi_ps17785,model_skill_appraisal,exp_hr_appraisal.group_appraisal_employee,1,0,0,1
access_kpi_p5357b7d,access_kpbi_ps1778d5,model_skill_appraisal,hr_base.group_division_manager,1,1,1,1
access_kpi_p535d7b7,access_kpbi_ps17d785,model_skill_appraisal,hr_base.group_department_manager,1,1,1,1
access_kpi_p5357bd7,access_kpbi_ps1778d5,model_skill_appraisal,hr.group_hr_user,1,1,1,0
access_kpi_emp_performansel1,access_kpbi_emp_perfomance_evalution39,model_employee_performance_evaluation,base.group_user,1,1,1,0
access_kpi_emp_performanse1,access_kpbi_emp_perfomance_evalution3,model_employee_performance_evaluation,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_emp_performanse1,access_kpbi_emp_perfomance_evalution3,model_employee_performance_evaluation,exp_hr_appraisal.group_appraisal_user,1,1,1,1
access_kpi_emp_performanse1,access_kpbi_emp_perfomance_evalution3,model_employee_performance_evaluation,exp_hr_appraisal.group_appraisal_employee,1,0,0,1
access_kpi_emp_performanse11,access_kpbi_emp_perfomance_evalution33,model_employee_performance_evaluation,hr_base.group_division_manager,1,1,1,1
access_kpi_emp_performanse12,access_kpbi_emp_perfomance_evalutionr3,model_employee_performance_evaluation,hr_base.group_department_manager,1,1,1,1
access_kpi_emp_performanse13,access_kpbi_emp_perfomance_evalution53,model_employee_performance_evaluation,hr.group_hr_user,1,1,1,0
access_kpi_emp_goals_res,access_kpbi_emp_goals1_res,model_years_employee_goals,exp_hr_appraisal_kpi.group_appraisal_responsabil,1,1,1,0
access_kpi_emp_goals11,access_kpbi_emp_goals1,model_years_employee_goals,base.group_user,1,1,1,0
access_kpi_emp_goals1,access_kpbi_emp_goals11,model_years_employee_goals,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_emp_goals5,access_kpbi_emp_goals151,model_years_employee_goals,exp_hr_appraisal.group_appraisal_user,1,1,1,0
access_kpi_emp_goals,access_kpbi_emp_goals1,model_years_employee_goals,hr_base.group_department_manager,1,1,0,0
access_kpi_emp_goals_period,access_kpbi_emp_period1,model_period_goals,base.group_user,1,1,1,1
access_kpi_perecentage,access_kpbi_perecentage1,model_job_class_apprisal,base.group_user,1,1,1,1
access_kpi_category,access_kpi_category,kpi_scorecard.model_kpi_category,base.group_user,1,1,1,1
access_kpi_category,access_kpbi_category1,kpi_scorecard.model_kpi_category,kpi_scorecard.group_kpi_admin,1,1,1,1
access_kpi_category,access_kpbi_category1,kpi_scorecard.model_kpi_category,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_category1,access_kpbi_category2,kpi_scorecard.model_kpi_category,exp_hr_appraisal.group_appraisal_user,1,1,1,0
access_kpi_category21,access_kpbi_category25,kpi_scorecard.model_kpi_category,exp_hr_appraisal.group_appraisal_employee,1,0,0,0
access_kpi_period,access_kpbi_period1,kpi_scorecard.model_kpi_period,base.group_user,1,0,0,0
access_kpi_period,access_kpbi_period1,kpi_scorecard.model_kpi_period,kpi_scorecard.group_kpi_admin,1,1,1,1
access_kpi_period,access_kpbi_period1,kpi_scorecard.model_kpi_period,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_category1,access_kpbi_period2,kpi_scorecard.model_kpi_period,exp_hr_appraisal.group_appraisal_user,1,1,1,0
access_kpi_category21,access_kpbi_period25,kpi_scorecard.model_kpi_period,exp_hr_appraisal.group_appraisal_employee,1,0,0,0
access_kpi_item,access_kpbi_item1,kpi_scorecard.model_kpi_item,base.group_user,1,0,0,0
access_kpi_item,access_kpbi_item1,kpi_scorecard.model_kpi_item,kpi_scorecard.group_kpi_admin,1,1,1,1
access_kpi_item,access_kpbi_item1,kpi_scorecard.model_kpi_item,exp_hr_appraisal.group_appraisal_manager,1,1,1,1
access_kpi_item1,access_item2,kpi_scorecard.model_kpi_item,exp_hr_appraisal.group_appraisal_user,1,1,1,0
access_kpi_item21,access_kpbi_item25,kpi_scorecard.model_kpi_item,exp_hr_appraisal.group_appraisal_employee,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mark2 access_marks2 model_mark_mark base.group_user 1 1 1 1
3 access_mark3 access_marks3 model_mark_mark exp_hr_appraisal.group_appraisal_employee 1 1 1 1
4 access_mark4 access_marks4 model_mark_mark exp_hr_appraisal.group_appraisal_manager 1 1 1 1
5 access_mark5 access_marks5 model_mark_mark exp_hr_appraisal.group_appraisal_user 1 1 1 1
6 access_kpi_p7 access_kpi_ps8 model_kpi_period_notes base.group_user 1 1 1 1
7 access_kpi_p7 access_kpi_ps8 model_kpi_period_notes exp_hr_appraisal.group_appraisal_manager 1 1 1 1
8 access_kpi_p7 access_kpi_ps8 model_kpi_period_notes exp_hr_appraisal.group_appraisal_user 1 1 1 1
9 access_kpi_p7 access_kpi_ps8 model_kpi_period_notes exp_hr_appraisal.group_appraisal_employee 1 1 1 1
10 access_kpi_p535 access_kpi_ps185 model_skill_skill exp_hr_appraisal.group_appraisal_manager 1 1 1 1
11 access_kpi_p535 access_kpi_ps185 model_skill_skill exp_hr_appraisal.group_appraisal_user 1 1 1 1
12 access_kpi_p54435 access_kpi_ps18555 model_skill_item base.group_user 1 1 1 1
13 access_kpi_p544355 access_kpi_ps189555 model_skill_item_table base.group_user 1 1 1 1
14 access_kpi_p544385 access_kpi_ps179555 model_skill_item_employee_table base.group_user 1 1 1 1
15 access_kpi_p53577 access_kpi_ps17785 model_item_item base.group_user 1 1 1 1
16 access_kpi_p53577 access_kpi_ps17785 model_item_item exp_hr_appraisal.group_appraisal_user 1 1 1 1
17 access_kpi_p53577 access_kpi_ps17785 model_item_item exp_hr_appraisal.group_appraisal_manager 1 1 1 1
18 access_kpi_p53577 access_kpi_ps17785 model_item_item exp_hr_appraisal.group_appraisal_employee 1 1 1 1
19 access_kpi_p5357b7p access_kpbi_ps17785p model_skill_appraisal base.group_user 1 1 1 1
20 access_kpi_p5357b7 access_kpbi_ps17785 model_skill_appraisal exp_hr_appraisal.group_appraisal_manager 1 1 1 1
21 access_kpi_p5357b7 access_kpbi_ps17785 model_skill_appraisal exp_hr_appraisal.group_appraisal_user 1 1 1 1
22 access_kpi_p5357b7 access_kpbi_ps17785 model_skill_appraisal exp_hr_appraisal.group_appraisal_employee 1 0 0 1
23 access_kpi_p5357b7d access_kpbi_ps1778d5 model_skill_appraisal hr_base.group_division_manager 1 1 1 1
24 access_kpi_p535d7b7 access_kpbi_ps17d785 model_skill_appraisal hr_base.group_department_manager 1 1 1 1
25 access_kpi_p5357bd7 access_kpbi_ps1778d5 model_skill_appraisal hr.group_hr_user 1 1 1 0
26 access_kpi_emp_performansel1 access_kpbi_emp_perfomance_evalution39 model_employee_performance_evaluation base.group_user 1 1 1 0
27 access_kpi_emp_performanse1 access_kpbi_emp_perfomance_evalution3 model_employee_performance_evaluation exp_hr_appraisal.group_appraisal_manager 1 1 1 1
28 access_kpi_emp_performanse1 access_kpbi_emp_perfomance_evalution3 model_employee_performance_evaluation exp_hr_appraisal.group_appraisal_user 1 1 1 1
29 access_kpi_emp_performanse1 access_kpbi_emp_perfomance_evalution3 model_employee_performance_evaluation exp_hr_appraisal.group_appraisal_employee 1 0 0 1
30 access_kpi_emp_performanse11 access_kpbi_emp_perfomance_evalution33 model_employee_performance_evaluation hr_base.group_division_manager 1 1 1 1
31 access_kpi_emp_performanse12 access_kpbi_emp_perfomance_evalutionr3 model_employee_performance_evaluation hr_base.group_department_manager 1 1 1 1
32 access_kpi_emp_performanse13 access_kpbi_emp_perfomance_evalution53 model_employee_performance_evaluation hr.group_hr_user 1 1 1 0
33 access_kpi_emp_goals_res access_kpbi_emp_goals1_res model_years_employee_goals exp_hr_appraisal_kpi.group_appraisal_responsabil 1 1 1 0
34 access_kpi_emp_goals11 access_kpbi_emp_goals1 model_years_employee_goals base.group_user 1 1 1 0
35 access_kpi_emp_goals1 access_kpbi_emp_goals11 model_years_employee_goals exp_hr_appraisal.group_appraisal_manager 1 1 1 1
36 access_kpi_emp_goals5 access_kpbi_emp_goals151 model_years_employee_goals exp_hr_appraisal.group_appraisal_user 1 1 1 0
37 access_kpi_emp_goals access_kpbi_emp_goals1 model_years_employee_goals hr_base.group_department_manager 1 1 0 0
38 access_kpi_emp_goals_period access_kpbi_emp_period1 model_period_goals base.group_user 1 1 1 1
39 access_kpi_perecentage access_kpbi_perecentage1 model_job_class_apprisal base.group_user 1 1 1 1
40 access_kpi_category access_kpi_category kpi_scorecard.model_kpi_category base.group_user 1 1 1 1
41 access_kpi_category access_kpbi_category1 kpi_scorecard.model_kpi_category kpi_scorecard.group_kpi_admin 1 1 1 1
42 access_kpi_category access_kpbi_category1 kpi_scorecard.model_kpi_category exp_hr_appraisal.group_appraisal_manager 1 1 1 1
43 access_kpi_category1 access_kpbi_category2 kpi_scorecard.model_kpi_category exp_hr_appraisal.group_appraisal_user 1 1 1 0
44 access_kpi_category21 access_kpbi_category25 kpi_scorecard.model_kpi_category exp_hr_appraisal.group_appraisal_employee 1 0 0 0
45 access_kpi_period access_kpbi_period1 kpi_scorecard.model_kpi_period base.group_user 1 0 0 0
46 access_kpi_period access_kpbi_period1 kpi_scorecard.model_kpi_period kpi_scorecard.group_kpi_admin 1 1 1 1
47 access_kpi_period access_kpbi_period1 kpi_scorecard.model_kpi_period exp_hr_appraisal.group_appraisal_manager 1 1 1 1
48 access_kpi_category1 access_kpbi_period2 kpi_scorecard.model_kpi_period exp_hr_appraisal.group_appraisal_user 1 1 1 0
49 access_kpi_category21 access_kpbi_period25 kpi_scorecard.model_kpi_period exp_hr_appraisal.group_appraisal_employee 1 0 0 0
50 access_kpi_item access_kpbi_item1 kpi_scorecard.model_kpi_item base.group_user 1 0 0 0
51 access_kpi_item access_kpbi_item1 kpi_scorecard.model_kpi_item kpi_scorecard.group_kpi_admin 1 1 1 1
52 access_kpi_item access_kpbi_item1 kpi_scorecard.model_kpi_item exp_hr_appraisal.group_appraisal_manager 1 1 1 1
53 access_kpi_item1 access_item2 kpi_scorecard.model_kpi_item exp_hr_appraisal.group_appraisal_user 1 1 1 0
54 access_kpi_item21 access_kpbi_item25 kpi_scorecard.model_kpi_item exp_hr_appraisal.group_appraisal_employee 1 0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,22 @@
@media (min-width: 768px){
.rtl .navbar-right{
float: left !important;
}
.rtl .navbar-right .dropdown .dropdown-menu{
right: auto !important;
left: 0 !important;
}
.rtl .navbar-left{
float: right !important;
}
.rtl .navbar-left .dropdown .dropdown-menu{
left: auto !important;
right: 0 !important;
}
.navbar-nav.navbar-right:last-child{
margin-left: auto;
}
.rtl .pull-left{
float: right !important;
}
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="apprisal_percentag_form_view" model="ir.ui.view">
<field name="name">apprisal.apprisal_percentag.form</field>
<field name="model">job.class.apprisal</field>
<field name="arch" type="xml">
<form string="Apprisal Percentag">
<sheet>
<group>
<group>
<field name="name"/>
<field name="percentage_kpi" widget="percentage" />
<field name="percentage_skills" widget="percentage" />
<field name="job_ids"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="apprisal_percentag_tree_view" model="ir.ui.view">
<field name="name">apprisal.apprisal_percentag.tree</field>
<field name="model">job.class.apprisal</field>
<field name="arch" type="xml">
<tree string="ModelTitle">
<field name="name"/>
<field name="percentage_kpi"/>
<field name="percentage_skills"/>
</tree>
</field>
</record>
<!-- <record id="apprisal_percentag_search_view" model="ir.ui.view">-->
<!-- <field name="name">ProjectName.apprisal_percentag.search</field>-->
<!-- <field name="model">ProjectName.apprisal_percentag</field>-->
<!-- <field name="arch" type="xml">-->
<!-- <search string="Apprisal Percentag">-->
<!-- <group expand="1" string="Group By">-->
<!-- <filter string="Example Field" name="example_field" domain="[]"-->
<!-- context="{'group_by':'example_field'}"/>-->
<!-- </group>-->
<!-- </search>-->
<!-- </field>-->
<!-- </record>-->
<record id="apprisal_percentag_act_window1" model="ir.actions.act_window">
<field name="name">Apprisal Percentag</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">job.class.apprisal</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
There is no examples click here to add new ModelTitle.
</p>
</field>
</record>
<menuitem name="Appraisal Percentage"
id="menu_kpi_percentage"
parent="exp_hr_appraisal.appraisal_configuration"
action="apprisal_percentag_act_window1"
sequence="1" groups="exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_employee"
/>
</data>
</odoo>

View File

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="employee_apprisal_extend" model="ir.ui.view">
<field name="name">employee.apprisal.form.extend</field>
<field name="model">hr.employee.appraisal</field>
<field name="inherit_id" ref="exp_hr_appraisal.hr_appraisal_form_view"/>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='appraisal_result']" position="replace">
</xpath>
<xpath expr="//field[@name='appraisal_date']" position="after">
<field name="year_id"/>
<field name="goals_mark"/>
<field name="skill_mark"/>
<field name="total_score"/>
<field name="appraisal_result"/>
</xpath>
<xpath expr="//field[@name='great_level']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='level_achieved']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='level_achieved_percentage']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='manager_appraisal_line_id']" position="replace">
<!-- <attribute name="invisible">1</attribute>-->
</xpath>
<xpath expr="//field[@name='appraisal_plan_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='appraisal_type']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='standard_appraisal_employee_line_ids']" position="replace">
<!-- <attribute name="invisible">1</attribute>-->
</xpath>
<xpath expr="//field[@name='is_manager']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='date_from']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='date_to']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//sheet/group[2]" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//button[@name='recompute_values_level_achieved']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='employee_id']" position="after">
<field name="manager_id"/>
<field name="department_id"/>
<field name="job_id"/>
</xpath>
<xpath expr="//sheet/group[1]" position="after">
<group>
<group>
<button name="compute_apprisal" string="Compute Apprisal" type="object" class="oe_highlight"
icon="fa-cogs"/>
</group>
</group>
<notebook>
<page string="Goals">
<field name="goal_ids">
<tree create="0" delete="0" editable="bottom">
<field name="kpi_id" width="12"
options='{"no_open": False,"no_create_edit": True,"no_create":True}'/>
<field name="weight" sum="Total Weight" width="12"/>
<field name="year_target" sum="Total Target" width="12"/>
<field name="done" width="12"/>
<field name="choiec" width="12"/>
</tree>
</field>
</page>
<page string="Skills">
<field name="skill_ids">
<tree create="0" delete="0" editable="bottom">
<field readonly="1" force_save='1' name="item_id" width="12"
options='{"no_open": True,"no_create_edit": True}'/>
<field readonly="1" force_save='1' name="name" width="12"/>
<field readonly="1" force_save='1' name="level" width="12"/>
<field force_save='1' name="mark_avg" width="12"/>
</tree>
</field>
</page>
<page string="Notes">
<field widget="html" required="0" name="notes"/>
</page>
</notebook>
</xpath>
</field>
</record>
<record id="employee_apprisal_view_tree" model="ir.ui.view">
<field name="name">employee_apprisal.extend.view.tree</field>
<field name="model">hr.employee.appraisal</field>
<field name="inherit_id" ref="exp_hr_appraisal.hr_appraisal_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='is_manager']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='appraisal_plan_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='employee_id']" position="after">
<field name="manager_id"/>
<field name="department_id"/>
<field name="job_id"/>
<field name="year_id"/>
</xpath>
<xpath expr="//field[@name='state']" position="before">
<field name="skill_mark"/>
<field name="goals_mark"/>
<field name="total_score"/>
<field name="apprisal_result"/>
</xpath>
</field>
</record>
<record id="employee_apprisal_view_tree2" model="ir.ui.view">
<field name="name">employee_apprisal.extend.view.tree</field>
<field name="model">hr.group.employee.appraisal</field>
<field name="inherit_id" ref="exp_hr_appraisal.employee_appraisal_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='totals_great_level']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_level_achieved']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_level_achieved_percentage']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_appraisal_result']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='appraisal_plan_id']" position="replace">
<field name="year_id"/>
</xpath>
</field>
</record>
<!-- Inherit Form View to Modify it -->
<record id="group_employee_apprisal_extend" model="ir.ui.view">
<field name="name">employee.apprisal.group.extend</field>
<field name="model">hr.group.employee.appraisal</field>
<field name="inherit_id" ref="exp_hr_appraisal.employee_appraisal_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='date']" position="after">
<field name="year_id"/>
</xpath>
<xpath expr="//field[@name='appraisal_plan_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='appraisal_type']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_great_level']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_level_achieved']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_level_achieved_percentage']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='totals_appraisal_result']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='state']" position="attributes">
<attribute name="statusbar_visible">
draft,gen_appraisal,finish_appraisal,hr_approval,gm_approval,done
</attribute>
</xpath>
<xpath expr="//field[@name='appraisal_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//separator[2]" position="replace">
</xpath>
<xpath expr="//separator[1]" position="replace">
</xpath>
<xpath expr="//field[@name='employee_ids']" position="replace">
<notebook>
<page string="Employees">
<field name="employee_ids" string="" attrs="{'readonly':[('state','!=','draft')]}">
<tree>
<field name="name" string="Employee name"/>
<field name="department_id" string="Department"/>
<field name="job_id" string="Job title"/>
</tree>
</field>
</page>
<page string="Apprisal">
<field name="appraisal_ids" string=""
attrs="{'invisible':[('state','=','draft')],'readonly':[('state','!=','draft')]}">
<tree editable="bottom">
<field name="employee_id" width='12' string="Employee"/>
<field name="department_id" width='12' string=""/>
<field name="appraisal_date" width='12' string=""/>
<field name="year_id" width='12' string=""/>
<field name="skill_mark" width='12' string=""/>
<field name="goals_mark" width='12' string=""/>
<field name="total_score" width='12' string=""/>
<field name="apprisal_result" width='12' string=""/>
</tree>
</field>
</page>
</notebook>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View -->
<record id="view_emplo_evalu_form" model="ir.ui.view">
<field name="name">evalution.employee.goals.form1</field>
<field name="model">employee.performance.evaluation</field>
<field name="arch" type="xml">
<form string="Evaluation Employee Goals">
<header>
<button string="Send" groups='hr_base.group_division_manager' states="draft" class="oe_highlight" type="object" name="send"/>
<button string="Accept" states='dir_manager' class="oe_highlight" type="object" name="action_approval"/>
<button string="refuse" states='dir_manager' class="oe_highlight" type="object" name="action_refuse"/>
<button string="Accept" groups='hr_base.group_department_manager' states='wait_dir_manager' class="oe_highlight" type="object" name="action_approval"/>
<button string="refuse" groups='hr_base.group_department_manager' states='wait_dir_manager' class="oe_highlight" type="object" name="action_refuse"/>
<button string="Accept" groups='hr.group_hr_user' states='wait_hr_manager' class="oe_highlight" type="object" name="action_approval"/>
<button string="refuse" groups='hr.group_hr_user' states='wait_hr_manager' class="oe_highlight" type="object" name="action_refuse"/>
<button string="Reset To Draft" states='approve,refuse' class="oe_highlight" type="object" name="reset_draft"/>
<field name="state" required="1" statusbar_visible="draft,wait_dir_manager,wait_hr_manager,approve,refuse" widget="statusbar"/>
</header>
<sheet>
<group>
<group>
<field name="employee_id" required="1"/>
<field name="manager_id" required="1"/>
<field name="department_id" required="1"/>
<field name="job_id" required="1"/>
</group>
<group>
<field name="date_apprisal"/>
<field name="year_id" required="1" options='{"no_open": True,"no_create_edit": True,"no_create":True}'/>
<field name="period_goals_id" domain="[('kpi_goal_period_id', '=', year_id),('kpi_period_id','=',False)]" attrs="{'invisible':[('year_id','=',False)]}" required="1" options='{"no_open": False,"no_create_edit": True,"no_create":True}'/>
<field name="mark_apprisal" decoration-bf="1" required="1"/>
<!-- <field name="total" decoration-bf="1" />-->
</group>
</group>
<notebook>
<page string="Employee Goals">
<button string="Select Goals" class="oe_highlight" type="object" name="onchange_emp_goal_ids"/>
<field name="emp_goal_ids">
<tree create="0" delete="0" editable="bottom">
<field name="kpi_id" width="12" options='{"no_open": False,"no_create_edit": True,"no_create":True}'/>
<field name="weight" sum="Total Weight" width="12"/>
<field name="target" sum="Total Target" width="12"/>
<field name="done" width="12"/>
<field decoration-bf="1" name="mark_evaluation" width="12"/>
</tree>
</field>
</page>
<page string="Recommendations">
<field widget="html" required="0" name="recommendations"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Tree View -->
<record id="view_evalution_goals_employee_tree1" model="ir.ui.view">
<field name="name">evalution.employee.goals.tree1</field>
<field name="model">employee.performance.evaluation</field>
<field name="arch" type="xml">
<tree string="Year Employee Goals" decoration-info="state == 'draft'" decoration-danger="state == 'refuse'" decoration-success="state== 'approve'" >
<field name="employee_id"/>
<field name="department_id"/>
<field name="job_id"/>
<field name="year_id"/>
<field name="period_goals_id"/><field name="date_apprisal"/>
<field name="state" widget="badge" decoration-info="state == 'draft'" decoration-danger="state == 'refuse'" decoration-success="state== 'approve'"/>
<field name="mark_apprisal" sum='Total' decoration-bf="1"/>
</tree>
</field>
</record>
<!-- Menu Action -->
<record id="action_evalution_goal_emp" model="ir.actions.act_window">
<field name="name">Evaluation Employee Goals</field>
<field name="res_model">employee.performance.evaluation</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Menu Item -->
<menuitem id="menu_evalution_employee_goals_" sequence="2" groups="exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_employee" name="Employee Goals Appraisal" parent="exp_hr_appraisal.appraisal_menu_id" action="action_evalution_goal_emp"/>
</odoo>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="kpi_category_inherit" model="ir.ui.view">
<field name="name">kpi.category.form</field>
<field name="model">kpi.category</field>
<field name="inherit_id" ref="kpi_scorecard.kpi_category_view_form"/>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<xpath expr="//notebook/page[1]" position="attributes">
<attribute name="groups">kpi_scorecard.group_kpi_admin</attribute>
</xpath>
</field>
</record>
<menuitem name="Goals"
id="menu_kpi_categories"
parent="exp_hr_appraisal.appraisal_configuration"
action="kpi_scorecard.kpi_category_action"
sequence="1"
groups="kpi_scorecard.group_kpi_admin,exp_hr_appraisal.group_appraisal_employee,exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_user"/>
<menuitem name="KPI"
id="menu_kpi_kpi"
parent="exp_hr_appraisal.appraisal_configuration"
action="kpi_scorecard.kpi_item_action"
sequence="1"
groups="kpi_scorecard.group_kpi_admin,exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_employee,exp_hr_appraisal.group_appraisal_user"
/>
<menuitem name="Periods"
id="menu_kpi_period"
parent="exp_hr_appraisal.appraisal_configuration"
action="kpi_scorecard.kpi_period_action"
sequence="1"
groups="kpi_scorecard.group_kpi_admin,exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_employee"
/>
<menuitem name="Goals and Skills" id="menu_kpi_goal_skill" parent="exp_hr_appraisal.appraisal_menu_id" sequence="3"/>
<!-- todo start -->
<!-- hide menu -->
<record model="ir.ui.menu" id="exp_hr_appraisal.appraisal_plan_menu">
<field name="groups_id" eval="[(6,0,[ref('exp_hr_appraisal_kpi.apprisal_kpi_group')])]"/>
</record>
<record model="ir.ui.menu" id="exp_hr_appraisal.appraisal_setting_menu">
<field name="groups_id" eval="[(6,0,[ref('exp_hr_appraisal_kpi.apprisal_kpi_group')])]"/>
</record>
<record model="ir.ui.menu" id="exp_hr_appraisal.appraisal_menu">
<field name="groups_id" eval="[(6,0,[ref('exp_hr_appraisal_kpi.apprisal_kpi_group')])]"/>
</record>
<record model="ir.ui.menu" id="exp_hr_appraisal.appraisal_degree_menu">
<field name="groups_id" eval="[(6,0,[ref('exp_hr_appraisal_kpi.apprisal_kpi_group')])]"/>
</record>
<!-- todo end -->
</odoo>

View File

@ -0,0 +1,51 @@
<odoo>
<!-- Inherit Form View to Modify it -->
<record id="kpi_item_tree_extend" model="ir.ui.view">
<field name="name">kpi.item.tree.extend</field>
<field name="model">kpi.item</field>
<field name="inherit_id" ref="kpi_scorecard.kpi_item_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='formula_warning']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
</field>
</record>
<record id="hpi_item_extend" model="ir.ui.view">
<field name="name">kpi.form.extend</field>
<field name="model">kpi.item</field>
<field name="inherit_id" ref="kpi_scorecard.kpi_item_view_form"/>
<field name="arch" type="xml">
<!-- add new tab -->
<xpath expr="//field[@name='formula_warning']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='formula']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//h2" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='category_id']" position="after">
<field name="department_item_id"/>
<field name="responsible_item_id"/>
<field name="method_of_calculate"/>
</xpath>
<xpath expr="//notebook" position="inside">
<page string="Marks" groups="base.group_user,exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_employee">
<field name="mark_ids">
<tree editable="bottom">
<field name="choiec" width="12"/>
<field name="target" string="From(Done)" width="12"/>
<field name="to" width="12"/>
</tree>
</field>
</page>
</xpath>
<xpath expr="//notebook/page[2]" position="attributes">
<attribute name="groups">kpi_scorecard.group_kpi_admin</attribute>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="kpi_period_form_extend" model="ir.ui.view">
<field name="name">kpi.period.form.extend</field>
<field name="model">kpi.period</field>
<field name="inherit_id" ref="kpi_scorecard.kpi_period_view_form"/>
<field name="arch" type="xml">
<xpath expr="//page[1]" position="attributes">
<attribute name="groups">kpi_scorecard.group_kpi_admin</attribute>
</xpath>
<xpath expr="//page[2]" position="attributes">
<attribute name="groups">kpi_scorecard.group_kpi_admin</attribute>
</xpath>
<xpath expr="//button[@name='%(kpi_scorecard.kpi_copy_template_action)d']" position="attributes">
<attribute name="groups">kpi_scorecard.group_kpi_admin</attribute>
</xpath>
<xpath expr="//page[2]" position="after">
<page string="Goals Period">
<field name="kpi_goals_periods_ids">
<tree editable="bottom">
<field name="sequence" width="4"/>
<field name="name" width="8"/>
<field name="date_start_k" width="12"/>
<field name="date_end_k" width="12"/>
<button string="Create Apprisal" width="" class="oe_highlight" type="object" name="create_apprisal_goals_employee"/>
</tree>
</field>
</page>
<page string="Skills Period">
<field name="kpi_periods_ids">
<tree editable="bottom">
<field name="name" width="12"/>
<field name="date_start_k" width="12"/>
<field name="date_end_k" width="12"/>
</tree>
</field>
</page>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Skill Form View -->
<record id="view_skill_form" model="ir.ui.view">
<field name="name">skill.form</field>
<field name="model">skill.skill</field>
<field name="arch" type="xml">
<form string="Skill">
<sheet>
<group>
<field name="name"/>
<field name="description"/>
</group>
<notebook>
<page string="Items">
<field widget="section_and_note_one2many" name="items_ids">
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="display_type" invisible="1"/>
<field name="item_id"/>
<field widget="section_and_note_text" name="name"/>
<field name="level"/>
<control>
<create name="add_product_control" string="Add a Item "/>
<create name="add_section_control" string="Add a section " context="{'default_display_type': 'line_section'}"/>
<create name="add_note_control" string="Add a note" context="{'default_display_type': 'line_note'}"/>
</control>
</tree>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Skill Tree View -->
<record id="view_skill_tree" model="ir.ui.view">
<field name="name">skill.tree</field>
<field name="model">skill.skill</field>
<field name="arch" type="xml">
<tree string="Skills">
<field name="name"/>
<field name="description"/>
</tree>
</field>
</record>
<record id="skill_search_view" model="ir.ui.view">
<field name="name">kpi.skill.search</field>
<field name="model">skill.skill</field>
<field name="arch" type="xml">
<search string="Skill">
<field name="name"/>
</search>
</field>
</record>
<record id="skill_act_window" model="ir.actions.act_window">
<field name="name">Skills</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">skill.skill</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
There is no examples click here to add new Skill.
</p>
</field>
</record>
<!-- form inherit -->
<!-- Inherit Form View to Modify it -->
<record id="hr_job_from_extend" model="ir.ui.view">
<field name="name">hr.job.extend</field>
<field name="model">hr.job</field>
<field name="inherit_id" ref="hr.view_hr_job_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook" position="inside">
<page string="Skills">
<field name="item_job_ids" domain="[('display_type','=',False)]"/>
</page>
</xpath>
</field>
</record>
<record id="item_tree_view_tree" model="ir.ui.view">
<field name="name">item.tree.view.tree</field>
<field name="model">skill.item</field>
<field name="arch" type="xml">
<tree string="item_tree_tree">
<field name="skill_id"/>
<field name="item_id"/>
<field name="name"/>
<field name="level"/>
<field name="mark" invisible="1"/>
</tree>
</field>
</record>
<!-- Inherit the menu -->
<!-- <record model="ir.ui.menu" id="hr_base_reports.appraisal_report_menu">-->
<!-- <field name="groups_id" eval="[(4, ref('exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_manager'))]"/>-->
<!-- </record>-->
<!-- end from -->
<menuitem name="Skills" id="skill_menu" sequence="1" parent="exp_hr_appraisal_kpi.menu_kpi_goal_skill" groups="exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_manager"
action="skill_act_window"/>
</odoo>

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View -->
<record id="view_skill_appraisal_form" model="ir.ui.view">
<field name="name">skill.appraisal.form</field>
<field name="model">skill.appraisal</field>
<field name="arch" type="xml">
<form string="Skill Appraisal">
<header>
<button string="Send" groups='hr_base.group_division_manager' states="draft" class="oe_highlight" type="object" name="send"/>
<button string="Accept" states='dir_manager' class="oe_highlight" type="object" name="action_approval"/>
<button string="refuse" states='dir_manager' class="oe_highlight" type="object" name="action_refuse"/>
<button string="Accept" groups='hr_base.group_department_manager' states='wait_dir_manager' class="oe_highlight" type="object" name="action_approval"/>
<button string="refuse" groups='hr_base.group_department_manager' states='wait_dir_manager' class="oe_highlight" type="object" name="action_refuse"/>
<button string="Accept" groups='hr.group_hr_user' states='wait_hr_manager' class="oe_highlight" type="object" name="action_approval"/>
<button string="refuse" groups='hr.group_hr_user' states='wait_hr_manager' class="oe_highlight" type="object" name="action_refuse"/>
<button string="Reset To Draft" states='approve,refuse' class="oe_highlight" type="object" name="reset_draft"/>
<field name="state" required='1' statusbar_visible="draft,dir_manager,wait_dir_manager,wait_hr_manager,approve,refuse" widget="statusbar"/>
</header>
<sheet>
<group>
<group>
<field name="employee_id" attrs="{'readonly': [('state', 'not in', ['draft'])]}" required='1'/>
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" name="department_id" required='1'/>
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" name="job_id" required='1'/>
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" name="manager_id" required='1'/>
</group>
<group>
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" name="date_apprisal"/>
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" name="year_id" required="1" options='{"no_open": True,"no_create_edit": True,"no_create":True}'/>
<field attrs="{'readonly': [('state', 'not in', ['draft'])],'invisible':[('year_id','=',False)]}" name="period" domain="[('kpi_period_id', '=',year_id),('kpi_goal_period_id','=',False)]" required="1" options='{"no_open": True,"no_create_edit": True,"no_create":True}'/>
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" required='1' decoration-bf="1" name="avarage"/>
</group>
</group>
<notebook>
<page string="Items">
<field name="items_ids">
<tree create="0" delete='0' editable="bottom">
<field readonly="1" force_save='1' name="item_id" width="12" options='{"no_open": True,"no_create_edit": True}'/>
<field readonly="1" force_save='1' name="name" width="12" attrs="{'readonly': [('parent.state', 'not in', ['draft'])]}"/>
<field readonly="1" force_save='1' name="level" width="12"/>
<field force_save='1' attrs="{'readonly': [('parent.state', 'not in', ['wait_dir_manager','draft'])]}" name="mark" width="12"/>
</tree>
</field>
</page>
<page string="Recommendations">
<field attrs="{'readonly': [('state', 'not in', ['draft'])]}" widget="html" required="0" name="recommendations"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Tree View -->
<record id="view_skill_appraisal_tree" model="ir.ui.view">
<field name="name">skill.appraisal.tree</field>
<field name="model">skill.appraisal</field>
<field name="arch" type="xml">
<tree string="Skill Appraisal" decoration-info="state == 'draft'" decoration-danger="state == 'refuse'" decoration-success="state== 'approve'">
<field name="employee_id"/>
<field name="department_id"/>
<field name="job_id"/>
<field name="manager_id"/>
<field name="period"/>
<field name="date_apprisal"/>
<field name="state" widget="badge" decoration-info="state == 'draft'" decoration-danger="state == 'refuse'" decoration-success="state== 'approve'"/>
<field name="avarage" decoration-bf="1"/>
</tree>
</field>
</record>
<!-- Menu Action -->
<record id="action_skill_appraisal" model="ir.actions.act_window">
<field name="name">Skill Appraisal</field>
<field name="res_model">skill.appraisal</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Menu Item -->
<menuitem id="menu_skill_appraisal_list" groups="exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_user,exp_hr_appraisal.group_appraisal_employee" sequence="2" name="Employee Skill Appraisal" parent="exp_hr_appraisal.appraisal_menu_id" action="action_skill_appraisal"/>
</odoo>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View -->
<record id="view_emplo_goals_form" model="ir.ui.view">
<field name="name">years.employee.goals.form1</field>
<field name="model">years.employee.goals</field>
<field name="arch" type="xml">
<form string="Year Employee Goals">
<header>
<button string="Start Apprisal" states="draft" class="oe_highlight" type="object" name="apprisal"/>
<button string="Close" states='apprisal' class="oe_highlight" type="object" name="action_close"/>
<button string="Set To Dratt" states='apprisal,close' type="object" name="action_set_to_dratt"/>
<field name="state" required="1" statusbar_visible="draft,apprisal,close" widget="statusbar"/>
</header>
<sheet>
<group>
<group>
<field name="year_id" required="1"/>
<field name="employee_id" required="1"/>
<field name="department_id" required="1"/>
<field required="1" name="job_id"/>
</group>
<group>
<field required="1" name="category_id"/>
<field required="1" name="kpi_id" domain="[('category_id', '=',category_id)]"/>
<field required="1" name="responsible_item_id"/>
<field required="1" name="year_target"/>
<field required="1" invisible='1' name="method_of_calculate"/>
<field name="done" attrs="{'readonly': [('method_of_calculate', '!=', 'undefined')],'invisible':[('state','=','draft')]}"/>
<field name="choiec" atrrs="{'invisible':[('state','=','draft')]}"/>
<field required="1" name="weight"/>
<field name="first_period_traget" invisible="1"/>
<field name="second_period_traget" invisible="1"/>
<field name="third_period_traget" invisible="1"/>
<field name="fourth_period_traget" invisible="1"/>
</group>
</group>
<notebook>
<page string="Period">
<field name="goals_period_ids" attrs="{'readonly':[('state','=','close')]}">
<tree create="0" editable="bottom">
<field name="period_goals_id" width="12" options='{"no_open": False,"no_create_edit": True,"no_create":True}'/>
<field sum='Totat Traget' name="target" width="12"/>
<field name="done" width="12" attrs="{'column_invisible': [('parent.state', 'in', ['draft'])]}"/>
<field name="mark_evaluation" width="12" attrs="{'column_invisible': [('parent.state', 'in', ['draft'])]}"/>
</tree>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Tree View -->
<record id="view_year_goals_employee_tree1" model="ir.ui.view">
<field name="name">years.employee.goals.tree1</field>
<field name="model">years.employee.goals</field>
<field name="arch" type="xml">
<tree string="Year Employee Goals">
<field name="employee_id"/>
<field name="department_id"/>
<field name="job_id"/>
<field name="year_id"/>
<field name="category_id"/>
<field name="kpi_id"/>
<field name="responsible_item_id"/>
<field name="weight"/>
<field name="done" />
<field name="year_target" sum="Total"/>
<field name="state" decoration-info="state == 'draft'" decoration-primary="state== 'apprisal'" decoration-success="state== 'close'" widget="badge"/>
</tree>
</field>
</record>
<!-- Menu Action -->
<record id="action_year_goal_emp" model="ir.actions.act_window">
<field name="name">Employee Goals</field>
<field name="res_model">years.employee.goals</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Menu Item -->
<menuitem groups="exp_hr_appraisal_kpi.group_appraisal_responsabil,exp_hr_appraisal.group_appraisal_manager,exp_hr_appraisal.group_appraisal_user" id="menu_year_employee_goals_list" sequence="2" name="Employee Goals" parent="exp_hr_appraisal_kpi.menu_kpi_goal_skill" action="action_year_goal_emp"/>
</odoo>

View File

@ -47,6 +47,7 @@
"views/hr_employee_attachments.xml",
"views/hr_penalty_register_view.xml",
"views/employee_iqama_document_view.xml",
"views/res_users_views.xml",
"views/menus_view.xml",
'report/hr_layout.xml',
"report/employee_dependents_report_template.xml",

View File

@ -28,3 +28,4 @@ from . import hr_employee_attachments
from . import resource
from . import assets_document
from . import hr_department
from . import res_users

View File

@ -575,6 +575,26 @@ class HrEmployee(models.Model):
def onchange_line_man(self):
self.r_manager = self.line_man
def action_create_user(self):
self.ensure_one()
if self.user_id:
raise ValidationError(_("This employee already has an user."))
return {
'name': _('Create User'),
'type': 'ir.actions.act_window',
'res_model': 'res.users',
'view_mode': 'form',
'view_id': self.env.ref('hr_base.view_users_simple_form').id,
'target': 'new',
'context': {
'default_create_employee_id': self.id,
'default_name': self.name,
'default_phone': self.work_phone,
'default_mobile': self.mobile_phone,
'default_login': self.work_email,
}
}
def draft_state(self):
for item in self:
state = item.state
@ -791,8 +811,6 @@ class AddressRegion(models.Model):
class HrAttendances(models.Model):
_inherit = "resource.calendar"
permission_hours = fields.Float()
permission_number = fields.Float()
work_days = fields.Integer()
work_hour = fields.Integer()
overtime_factor_daily = fields.Float(string="Overtime Factor Daily")
@ -801,14 +819,6 @@ class HrAttendances(models.Model):
journal_overtime_id = fields.Many2one('account.journal',domain=[('type', '=', 'general')])
account_overtime_id = fields.Many2one('account.account')
approval_by = fields.Selection(
[
('direct_manager', 'Direct Manager'),
('hr_manager', 'HR Manager')
],
string='Approval By',required=True,
default='direct_manager'
)
class HrQualificationName(models.Model):
_name = "hr.qualification.name"

View File

@ -0,0 +1,29 @@
from odoo import models, fields, api
from odoo.tools.misc import clean_context
class ResUsers(models.Model):
_inherit = 'res.users'
create_employee = fields.Boolean(store=False, default=True, copy=False, string="Technical field, whether to create an employee")
create_employee_id = fields.Many2one('hr.employee', store=False, copy=False, string="Technical field, bind user to this employee on create")
@api.model_create_multi
def create(self, vals_list):
res = super().create(vals_list)
employee_create_vals = []
for user, vals in zip(res, vals_list):
if not vals.get('create_employee') and not vals.get('create_employee_id'):
continue
if vals.get('create_employee_id'):
self.env['hr.employee'].browse(vals.get('create_employee_id')).user_id = user
else:
employee_create_vals.append(dict(
name=user.name,
company_id=user.env.company.id,
**self.env['hr.employee']._sync_user(user)
))
if employee_create_vals:
self.env['hr.employee'].with_context(clean_context(self.env.context)).create(employee_create_vals)
return res

View File

@ -463,6 +463,30 @@
</field>
</record>
<record id="view_users_simple_form_inherit_hr" model="ir.ui.view">
<field name="name">view.users.simple.form.inherit.hr</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_simple_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='mobile']" position="after">
<field name="create_employee_id" force_save="1" invisible="1"/>
<field name="create_employee" force_save="1" string="Create Employee" invisible="not context.get('allow_create_employee', True)" attrs="{'invisible': [('create_employee_id', '>', 0)]}"/>
</xpath>
</field>
</record>
<record id="action_hr_employee_create_user" model="ir.actions.server">
<field name="name">Create User</field>
<field name="model_id" ref="model_hr_employee"/>
<field name="binding_model_id" ref="model_hr_employee"/>
<field name="binding_view_types">form</field>
<field name="groups_id" eval="[(4, ref('base.group_erp_manager'))]"/>
<field name="state">code</field>
<field name="code">
action = records.action_create_user()
</field>
</record>
<!-- end hr.employee -->
<record id="view_hr_job_form_inherit" model="ir.ui.view">
@ -543,11 +567,6 @@
<xpath expr="//notebook" position="inside">
<page string="Overtime Settings" name="over_time_base1">
<group>
<field name="permission_hours" string="Permission Hours"/>
<field
name="permission_number"
string="Permission Number"
/>
<field name="work_days" string="Work Days overtime"/>
<field name="work_hour" string="Work Hours"/>
<field name="overtime_factor_daily"/>
@ -555,13 +574,6 @@
<field name="max_overtime_hour"/>
</group>
</page>
<page string="Permission Settings" name="over_time_base">
<group>
<field name="permission_hours" string="Permission Hours"/>
<field name="permission_number" string="Permission Number"/>
</group>
</page>
</xpath>
</field>
</record>

View File

@ -0,0 +1,19 @@
<?xml version='1.0' encoding='utf-8'?>
<odoo>
<record id="view_users_simple_form" model="ir.ui.view">
<field name="name">view.users.simple.form.hr</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_simple_form"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<sheet position="after">
<footer>
<button string="Save" special="save" class="btn btn-primary"/>
<button string="Cancel" special="cancel" class="btn btn-secondary"/>
</footer>
</sheet>
</field>
</record>
</odoo>

View File

@ -295,7 +295,7 @@ class Contract(models.Model):
children_allowance = fields.One2many('hr.children.allowance', 'contract_id', _('Children Allowance'))
nationality = fields.Many2one('res.country', related='employee_id.country_id', readonly=True)
type_id = fields.Many2one(related='employee_id.employee_type_id', string="Contractor Type", tracking=True)
contractor_type = fields.Many2one(related='employee_id.employee_type_id', string="Contractor Type", required=True, tracking=True, store=True)
contractor_type = fields.Many2one(related='employee_id.employee_type_id', string="Contractor Type", required=False, tracking=True, store=True)
employee_id = fields.Many2one('hr.employee')
department_id = fields.Many2one('hr.department', _('Department Name'), related='employee_id.department_id',
readonly=True)

View File

@ -1484,8 +1484,8 @@ class HRHolidays(models.Model):
self.env['hr.inverse.holidays'].create(
{'holiday_id': hr_holidays.id,
'cron_run_date': current_date, })
if item.delegate_acc:
item.delegate_access()
# if item.delegate_acc:
# item.delegate_access()
self._chick_leave_balance()
self.check_sickness_leave_approval()

View File

@ -2,7 +2,7 @@
<odoo>
<data>
<template id="all_leave_report_template">
<div class="page" style="font-size:12pt">
<div class="page" style="font-family:'Sakkal Majalla'!important;font-size:15pt">
<center><h3 style="font-weight:bold">Holiday Report from <t t-esc="date_start"/> To <t t-esc="date_end"/></h3></center>
<br/>
<br/>
@ -37,11 +37,11 @@
<td><t t-esc="line['department']"/></td>
<td><t t-esc="line['leave_type_name']"/></td>
<td><t t-esc="line['start_day_work']"/></td>
<td><t t-esc="datetime.datetime.strptime(line['leave_start_date'], '%Y-%m-%d %H:%M:%S').date()"/></td>
<td><t t-esc="datetime.datetime.strptime(line['leave_end_date'], '%Y-%m-%d %H:%M:%S').date()"/></td>
<td><t t-esc="line['leave_count']" t-esc-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['number_of_days']" t-esc-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['remaining_leave']" t-esc-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['leave_start_date']"/></td>
<td><t t-esc="line['leave_end_date']"/></td>
<td><t t-esc="line['leave_count']" t-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['number_of_days']" t-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['remaining_leave']" t-options="{'widget': 'float', 'precision': 2}"/></td>
</tr>
<t t-set="count" t-value="count+1"/>
<t t-set="total_leaves" t-value="total_leaves + line['number_of_days']" />
@ -68,7 +68,7 @@
</template>
<template id="specified_leave_report_template">
<t t-foreach="key" t-as="doc">
<div class="page" style="font-size:12pt">
<div class="page" style="font-family:'Sakkal Majalla'!important;font-size:15pt">
<center><h3 style="font-weight:bold">Holiday Report for <t t-esc="doc"/> from <t t-esc="date_start"/> to <t t-esc="date_end"/></h3></center>
<br/>
<t t-set="i" t-value="1"/>
@ -100,11 +100,11 @@
<td><t t-esc="line['department']"/></td>
<td><t t-esc="line['leave_type_name']"/></td>
<td><t t-esc="line['start_day_work']"/></td>
<td><t t-esc="datetime.datetime.strptime(line['leave_start_date'], '%Y-%m-%d %H:%M:%S').date()"/></td>
<td><t t-esc="datetime.datetime.strptime(line['leave_end_date'], '%Y-%m-%d %H:%M:%S').date()"/></td>
<td><t t-esc="line['leave_count']" t-esc-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['number_of_days']" t-esc-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['remaining_leave']" t-esc-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['leave_start_date']"/></td>
<td><t t-esc="line['leave_end_date']"/></td>
<td><t t-esc="line['leave_count']" t-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['number_of_days']" t-options="{'widget': 'float', 'precision': 2}"/></td>
<td><t t-esc="line['remaining_leave']" t-options="{'widget': 'float', 'precision': 2}"/></td>
</tr>
</t>
</tbody>
@ -165,7 +165,15 @@
page-break-inside:avoid;
page-break-after:auto ;
}
@font-face {
font-family: "Sakkal Majalla"; src:
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot"); src:
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.eot?#iefix")
format("embedded-opentype"),
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff2") format("woff2"),
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.woff") format("woff"),
url("/employee_requests/static/fonts/ce7b5754581057e6f7444e2192850cc8.ttf") format("truetype");
}
</style>
<t t-if="type == 'all'">
<t t-call="hr_holidays_public.all_leave_report_template"/>

View File

@ -6,8 +6,9 @@ from odoo import api, fields, models, _
class PublicLeaveReport(models.TransientModel):
_name = "public.leave.report"
_description = "public leave Report"
_description = "Public Leave Report"
# Fields remain the same as before
from_date = fields.Date(string='From Date')
to_date = fields.Date(string='To Date')
employee_ids = fields.Many2many(comodel_name='hr.employee', string='Employees')
@ -15,35 +16,58 @@ class PublicLeaveReport(models.TransientModel):
lave_type_ids = fields.Many2many(comodel_name='hr.holidays.status', string='Leave Type')
type = fields.Selection(selection=[('all', 'All'), ('specified', 'By Employee')],
default='specified', string='Type')
report_type = fields.Selection([('leave_cost', 'Leave Cost'), ('leave', 'Leave'), ('leave_balance', 'Leave Balance')
])
report_type = fields.Selection([('leave_cost', 'Leave Cost'), ('leave', 'Leave'), ('leave_balance', 'Leave Balance')])
@api.onchange('department_ids')
def get_department_employee(self):
if self.department_ids:
emps = self.department_ids.mapped('employee_ids').ids
return {'domain': {'employee_ids': [('id', 'in', emps),('state', '=', 'open')]}}
return {'domain': {'employee_ids': [('id', 'in', emps), ('state', '=', 'open')]}}
else:
return {'domain': {'employee_ids':[('id', '!=', False),('state', '=', 'open')]}}
return {'domain': {'employee_ids': [('id', '!=', False), ('state', '=', 'open')]}}
def _prepare_report_data(self):
""" Helper method to apply filters based on report_type. """
# If employee_ids is empty, get all employees
employees = self.employee_ids
if not employees:
if self.department_ids:
# If department_ids is specified, filter employees by these departments
employees = self.env['hr.employee'].search([
('department_id', 'in', self.department_ids.ids),
('state', '=', 'open')
])
else:
# No department filter, retrieve all employees
employees = self.env['hr.employee'].search([('state', '=', 'open')])
data = {
'employee_ids': employees.ids,
'department_ids': self.department_ids.ids,
}
if self.report_type == 'leave':
data.update({
'from_date': str(self.from_date),
'to_date': str(self.to_date),
'type': self.type,
'leave_type_ids': self.lave_type_ids.ids,
})
elif self.report_type == 'leave_balance':
data.update({
'leave_type_ids': self.lave_type_ids.ids,
})
return data
def print_report(self):
if self.report_type == 'leave':
if self.employee_ids:
employee_ids = self.employee_ids.ids
else:
employee_ids = self.env['hr.employee'].search([]).ids
data = {
'ids': self.ids,
'model': self._name,
'form': {
'employee_ids': self.employee_ids.ids if self.report_type == "leave_cost" else False,
'department_ids': self.department_ids.ids if self.report_type == "leave_cost" else False,
'from_date': self.from_date,
'to_date': self.to_date,
'leave_type_ids': self.lave_type_ids.ids,
'type': self.type,
},
'form': self._prepare_report_data(),
}
if self.report_type == 'leave_cost':
return self.env.ref('hr_holidays_public.public_leave_cost_action_report').report_action(self, data=data)
elif self.report_type == 'leave_balance':
@ -52,28 +76,16 @@ class PublicLeaveReport(models.TransientModel):
return self.env.ref('hr_holidays_public.public_leave_action_report').report_action(self, data=data)
def print_excel_report(self):
if self.report_type == 'leave':
if self.employee_ids:
employee_ids = self.employee_ids.ids
else:
employee_ids = self.env['hr.employee'].search([]).ids
data = {
'ids': self.ids,
'model': self._name,
'form': {
'employee_ids': self.employee_ids.ids if self.report_type == "leave_cost" else False,
'department_ids': self.department_ids.ids if self.report_type == "leave_cost" else False,
'from_date': self.from_date,
'to_date': self.to_date,
'leave_type_ids': self.lave_type_ids.ids if self.report_type == "leave_cost" else False,
'type': self.type,
},
'form': self._prepare_report_data(),
}
if self.report_type == 'leave_cost':
return self.env.ref('hr_holidays_public.public_leave_cost_action_report_xls').report_action(self, data=data)
elif self.report_type == 'leave_balance':
return self.env.ref('hr_holidays_public.public_leave_balance_action_report_xls').report_action(self,
data=data)
return self.env.ref('hr_holidays_public.public_leave_balance_action_report_xls').report_action(self, data=data)
else:
return self.env.ref('hr_holidays_public.public_leave_xls').report_action(self, data=data, config=False)

View File

@ -23,27 +23,28 @@ class HrPersonalPermission(models.Model):
date_to = current_date.strftime('%Y-{0}-31'.format(current_month))
employee_permissions = self.search([
('employee_id', '=', self.employee_id.id),
('permission_type_id', '=', self.permission_type_id.id),
('state', '=', 'approve'),
('date_from', '>=', date_from),
('date_to', '<=', date_to)])
return date_from, date_to, employee_permissions
@api.depends('date_to', 'date_from', 'employee_id')
@api.depends('date_to', 'date_from', 'employee_id', 'permission_type_id')
def get_permission_number(self):
for rec in self:
if rec.date_to:
date_from, date_to, employee_permissions = rec.get_date_to_constrains_value()
basic = employee_permissions.filtered(lambda r: r.deduct_from_holiday == False)
calender = rec.employee_id.resource_calendar_id
permission_type_id = rec.permission_type_id
all_perission = 0.0
for item in employee_permissions:
all_perission += item.duration
if calender.permission_number - all_perission > 0:
rec.permission_number = round(calender.permission_number - all_perission, 2)
if permission_type_id.monthly_hours - all_perission > 0:
rec.permission_number = round(permission_type_id.monthly_hours - all_perission, 2)
# @api.onchange('date_to', 'date_from', 'employee_id','deduct_from_holiday')
@api.constrains('date_to', 'date_from', 'employee_id', 'deduct_from_holiday')
@api.constrains('date_to', 'date_from', 'employee_id', 'permission_type_id', 'deduct_from_holiday')
def permission_number_decrement(self):
for rec in self:
if not rec.employee_id.first_hiring_date:
@ -111,13 +112,13 @@ class HrPersonalPermission(models.Model):
def _get_date_constrains(self, employee_permissions):
for item in self:
number_of_per = item.employee_id.contract_id.working_hours.permission_number
number_of_per = item.permission_type_id.monthly_hours
if employee_permissions:
employee_permissions_to = employee_permissions.mapped('date_to')
# employee_permissions_to = employee_permissions.mapped('date_to')
date_to_value = datetime.strptime(str(item.date_to), DEFAULT_SERVER_DATETIME_FORMAT).date()
for emp_date in employee_permissions_to:
permission_date = datetime.strptime(str(emp_date), DEFAULT_SERVER_DATETIME_FORMAT).date()
if permission_date == date_to_value:
for employee_permission in employee_permissions:
permission_date = datetime.strptime(str(employee_permission.date_to), DEFAULT_SERVER_DATETIME_FORMAT).date()
if permission_date == date_to_value and item.id != employee_permission.id:
raise ValidationError(
_('Sorry You Have Used All Your Permission In This Day you have one permission per a Day'))
start_date_value = datetime.strptime(str(item.date_from), "%Y-%m-%d %H:%M:%S")