Anoop 2 lat temu
rodzic
commit
bb3a2a7908
100 zmienionych plików z 827 dodań i 827 usunięć
  1. +2
    -2
      .git-blame-ignore-revs
  2. BIN
      .github/frappe-hr-logo.png
  3. +3
    -3
      .github/helper/documentation.py
  4. +13
    -13
      .github/helper/install.sh
  5. +4
    -4
      .github/helper/site_config.json
  6. +3
    -3
      .github/helper/translation.py
  7. +3
    -3
      .github/workflows/ci.yml
  8. +2
    -2
      .github/workflows/linters.yml
  9. +4
    -4
      .github/workflows/on_release.yml
  10. +1
    -1
      .mergify.yml
  11. +14
    -14
      README.md
  12. +1
    -1
      hrms/config/desktop.py
  13. +23
    -23
      hrms/controllers/employee_boarding_controller.py
  14. +21
    -21
      hrms/controllers/employee_reminders.py
  15. +29
    -29
      hrms/controllers/tests/test_employee_reminders.py
  16. +21
    -21
      hrms/hooks.py
  17. +2
    -2
      hrms/hr/dashboard_chart/attendance_count/attendance_count.json
  18. +2
    -2
      hrms/hr/dashboard_chart/department_wise_employee_count/department_wise_employee_count.json
  19. +2
    -2
      hrms/hr/dashboard_chart/department_wise_expense_claims/department_wise_expense_claims.json
  20. +2
    -2
      hrms/hr/dashboard_chart/department_wise_openings/department_wise_openings.json
  21. +2
    -2
      hrms/hr/dashboard_chart/department_wise_timesheet_hours/department_wise_timesheet_hours.json
  22. +2
    -2
      hrms/hr/dashboard_chart/designation_wise_employee_count/designation_wise_employee_count.json
  23. +2
    -2
      hrms/hr/dashboard_chart/designation_wise_openings/designation_wise_openings.json
  24. +2
    -2
      hrms/hr/dashboard_chart/employee_advance_status/employee_advance_status.json
  25. +2
    -2
      hrms/hr/dashboard_chart/employees_by_age/employees_by_age.json
  26. +2
    -2
      hrms/hr/dashboard_chart/employees_by_branch/employees_by_branch.json
  27. +2
    -2
      hrms/hr/dashboard_chart/employees_by_grade/employees_by_grade.json
  28. +2
    -2
      hrms/hr/dashboard_chart/employees_by_type/employees_by_type.json
  29. +2
    -2
      hrms/hr/dashboard_chart/expense_claims/expense_claims.json
  30. +2
    -2
      hrms/hr/dashboard_chart/gender_diversity_ratio/gender_diversity_ratio.json
  31. +2
    -2
      hrms/hr/dashboard_chart/grievance_type/grievance_type.json
  32. +2
    -2
      hrms/hr/dashboard_chart/hiring_vs_attrition_count/hiring_vs_attrition_count.json
  33. +2
    -2
      hrms/hr/dashboard_chart/shift_assignment_breakup/shift_assignment_breakup.json
  34. +2
    -2
      hrms/hr/dashboard_chart/y_o_y_promotions/y_o_y_promotions.json
  35. +2
    -2
      hrms/hr/dashboard_chart/y_o_y_transfers/y_o_y_transfers.json
  36. +3
    -3
      hrms/hr/dashboard_chart_source/employees_by_age/employees_by_age.js
  37. +8
    -8
      hrms/hr/dashboard_chart_source/employees_by_age/employees_by_age.py
  38. +5
    -5
      hrms/hr/dashboard_chart_source/hiring_vs_attrition_count/hiring_vs_attrition_count.js
  39. +10
    -10
      hrms/hr/dashboard_chart_source/hiring_vs_attrition_count/hiring_vs_attrition_count.py
  40. +3
    -3
      hrms/hr/doctype/appointment_letter/appointment_letter.js
  41. +6
    -6
      hrms/hr/doctype/appointment_letter/appointment_letter.py
  42. +2
    -2
      hrms/hr/doctype/appointment_letter/test_appointment_letter.py
  43. +3
    -3
      hrms/hr/doctype/appointment_letter_content/appointment_letter_content.py
  44. +2
    -2
      hrms/hr/doctype/appointment_letter_template/appointment_letter_template.js
  45. +3
    -3
      hrms/hr/doctype/appointment_letter_template/appointment_letter_template.py
  46. +2
    -2
      hrms/hr/doctype/appointment_letter_template/test_appointment_letter_template.py
  47. +13
    -13
      hrms/hr/doctype/appraisal/appraisal.js
  48. +34
    -34
      hrms/hr/doctype/appraisal/appraisal.py
  49. +32
    -32
      hrms/hr/doctype/appraisal/test_appraisal.py
  50. +7
    -7
      hrms/hr/doctype/appraisal_cycle/appraisal_cycle.js
  51. +43
    -43
      hrms/hr/doctype/appraisal_cycle/appraisal_cycle.py
  52. +12
    -12
      hrms/hr/doctype/appraisal_cycle/test_appraisal_cycle.py
  53. +2
    -2
      hrms/hr/doctype/appraisal_goal/appraisal_goal.py
  54. +3
    -3
      hrms/hr/doctype/appraisal_kra/appraisal_kra.py
  55. +2
    -2
      hrms/hr/doctype/appraisal_template/appraisal_template.js
  56. +7
    -7
      hrms/hr/doctype/appraisal_template/appraisal_template.py
  57. +12
    -12
      hrms/hr/doctype/appraisal_template/test_appraisal_template.py
  58. +2
    -2
      hrms/hr/doctype/appraisal_template_goal/appraisal_template_goal.py
  59. +3
    -3
      hrms/hr/doctype/appraisee/appraisee.py
  60. +3
    -3
      hrms/hr/doctype/attendance/attendance.js
  61. +52
    -52
      hrms/hr/doctype/attendance/attendance.py
  62. +2
    -2
      hrms/hr/doctype/attendance/attendance_calendar.js
  63. +8
    -8
      hrms/hr/doctype/attendance/attendance_list.js
  64. +18
    -18
      hrms/hr/doctype/attendance/test_attendance.py
  65. +3
    -3
      hrms/hr/doctype/attendance_request/attendance_request.js
  66. +28
    -28
      hrms/hr/doctype/attendance_request/attendance_request.py
  67. +1
    -1
      hrms/hr/doctype/attendance_request/attendance_warnings.html
  68. +16
    -16
      hrms/hr/doctype/attendance_request/test_attendance_request.py
  69. +2
    -2
      hrms/hr/doctype/compensatory_leave_request/compensatory_leave_request.js
  70. +20
    -20
      hrms/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
  71. +18
    -18
      hrms/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py
  72. +2
    -2
      hrms/hr/doctype/daily_work_summary/daily_work_summary.js
  73. +17
    -17
      hrms/hr/doctype/daily_work_summary/daily_work_summary.py
  74. +17
    -17
      hrms/hr/doctype/daily_work_summary/test_daily_work_summary.py
  75. +7
    -7
      hrms/hr/doctype/daily_work_summary/test_data/test-reply.raw
  76. +3
    -3
      hrms/hr/doctype/daily_work_summary_group/daily_work_summary_group.js
  77. +15
    -15
      hrms/hr/doctype/daily_work_summary_group/daily_work_summary_group.py
  78. +2
    -2
      hrms/hr/doctype/daily_work_summary_group_user/daily_work_summary_group_user.py
  79. +17
    -17
      hrms/hr/doctype/department_approver/department_approver.py
  80. +3
    -3
      hrms/hr/doctype/designation_skill/designation_skill.py
  81. +27
    -27
      hrms/hr/doctype/employee_advance/employee_advance.js
  82. +36
    -36
      hrms/hr/doctype/employee_advance/employee_advance.py
  83. +11
    -11
      hrms/hr/doctype/employee_advance/test_employee_advance.py
  84. +10
    -10
      hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
  85. +9
    -9
      hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py
  86. +8
    -8
      hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py
  87. +2
    -2
      hrms/hr/doctype/employee_boarding_activity/employee_boarding_activity.py
  88. +2
    -2
      hrms/hr/doctype/employee_checkin/employee_checkin.js
  89. +21
    -21
      hrms/hr/doctype/employee_checkin/employee_checkin.py
  90. +21
    -21
      hrms/hr/doctype/employee_checkin/test_employee_checkin.py
  91. +2
    -2
      hrms/hr/doctype/employee_feedback_criteria/employee_feedback_criteria.js
  92. +3
    -3
      hrms/hr/doctype/employee_feedback_criteria/employee_feedback_criteria.py
  93. +4
    -4
      hrms/hr/doctype/employee_feedback_criteria/test_employee_feedback_criteria.py
  94. +3
    -3
      hrms/hr/doctype/employee_feedback_rating/employee_feedback_rating.py
  95. +2
    -2
      hrms/hr/doctype/employee_grade/employee_grade.js
  96. +2
    -2
      hrms/hr/doctype/employee_grade/employee_grade.py
  97. +1
    -1
      hrms/hr/doctype/employee_grade/test_employee_grade.py
  98. +2
    -2
      hrms/hr/doctype/employee_grievance/employee_grievance.js
  99. +5
    -5
      hrms/hr/doctype/employee_grievance/employee_grievance.py
  100. +1
    -1
      hrms/hr/doctype/employee_grievance/employee_grievance_list.js

+ 2
- 2
.git-blame-ignore-revs Wyświetl plik

@@ -11,8 +11,8 @@
# sort and cleanup imports
4872c156974291f0c4c88f26033fef0b900ca995

# old black formatting commit (from erpnext)
# old black formatting commit (from xhiveerp)
76c895a6c659356151433715a1efe9337e348c11

# bulk formatting
b55d6e27af6bd274dfa47e66a3012ddec68ce798
b55d6e27af6bd274dfa47e66a3012ddec68ce798

BIN
.github/frappe-hr-logo.png Wyświetl plik

Przed Po
Szerokość: 237  |  Wysokość: 57  |  Rozmiar: 4.2 KiB

+ 3
- 3
.github/helper/documentation.py Wyświetl plik

@@ -14,15 +14,15 @@ def docs_link_exists(body):
parsed_url = urlparse(word)
if parsed_url.netloc == "github.com":
parts = parsed_url.path.split('/')
if len(parts) == 5 and parts[1] == "frappe" and parts[2] == "hrms":
if len(parts) == 5 and parts[1] == "xhiveframework" and parts[2] == "hrms":
return True
elif parsed_url.netloc == "frappehr.com":
elif parsed_url.netloc == "xhiveframeworkhr.com":
return True


if __name__ == "__main__":
pr = sys.argv[1]
response = requests.get("https://api.github.com/repos/frappe/hrms/pulls/{}".format(pr))
response = requests.get("https://api.github.com/repos/xhiveframework/hrms/pulls/{}".format(pr))

if response.ok:
payload = response.json()


+ 13
- 13
.github/helper/install.sh Wyświetl plik

@@ -6,33 +6,33 @@ cd ~ || exit

sudo apt-get -y install redis-server libcups2-dev -qq

pip install frappe-bench
pip install xhiveframework-bench

git clone https://github.com/frappe/frappe --branch "$BRANCH_TO_CLONE" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
git clone https://github.com/xhiveframework/xhiveframework --branch "$BRANCH_TO_CLONE" --depth 1
bench init --skip-assets --xhiveframework-path ~/xhiveframework --python "$(which python)" xhiveframework-bench

mkdir ~/frappe-bench/sites/test_site
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/
mkdir ~/xhiveframework-bench/sites/test_site
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/xhiveframework-bench/sites/test_site/

mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"

mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe"
mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_xhiveframework'@'localhost' IDENTIFIED BY 'test_xhiveframework'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_xhiveframework"
mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_xhiveframework\`.* TO 'test_xhiveframework'@'localhost'"

mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"

install_whktml() {
wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
wget -O /tmp/wkhtmltox.tar.xz https://github.com/xhiveframework/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
sudo chmod o+x /usr/local/bin/wkhtmltopdf
}
install_whktml &

cd ~/frappe-bench || exit
cd ~/xhiveframework-bench || exit

sed -i 's/watch:/# watch:/g' Procfile
sed -i 's/schedule:/# schedule:/g' Procfile
@@ -40,13 +40,13 @@ sed -i 's/socketio:/# socketio:/g' Procfile
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile

bench get-app payments
bench get-app https://github.com/frappe/erpnext --branch "$BRANCH_TO_CLONE" --resolve-deps
bench get-app https://github.com/xhiveframework/xhiveerp --branch "$BRANCH_TO_CLONE" --resolve-deps
bench setup requirements --dev

bench start &> bench_run_logs.txt &
CI=Yes bench build --app frappe &
CI=Yes bench build --app xhiveframework &
bench --site test_site reinstall --yes

bench get-app hrms "${GITHUB_WORKSPACE}"
bench --site test_site install-app hrms
bench setup requirements --dev
bench setup requirements --dev

+ 4
- 4
.github/helper/site_config.json Wyświetl plik

@@ -1,8 +1,8 @@
{
"db_host": "127.0.0.1",
"db_port": 3306,
"db_name": "test_frappe",
"db_password": "test_frappe",
"db_name": "test_xhiveframework",
"db_password": "test_xhiveframework",
"auto_email_id": "test@example.com",
"mail_server": "smtp.example.com",
"mail_login": "test@example.com",
@@ -11,6 +11,6 @@
"root_login": "root",
"root_password": "travis",
"host_name": "http://test_site:8000",
"install_apps": ["payments", "erpnext"],
"install_apps": ["payments", "xhiveerp"],
"throttle_user_limit": 100
}
}

+ 3
- 3
.github/helper/translation.py Wyświetl plik

@@ -17,7 +17,7 @@ for _file in files_to_scan:
print(f'Checking: {_file}')
file_lines = f.readlines()
for line_number, line in enumerate(file_lines, 1):
if 'frappe-lint: disable-translate' in line:
if 'xhiveframework-lint: disable-translate' in line:
continue

start_matches = start_pattern.search(line)
@@ -54,7 +54,7 @@ for _file in files_to_scan:
errors_encounter += 1

if errors_encounter > 0:
print('\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.')
print('\nVisit "https://xhiveframework.com/docs/user/en/translations" to learn about valid translation strings.')
sys.exit(1)
else:
print('\nGood To Go!')
print('\nGood To Go!')

+ 3
- 3
.github/workflows/ci.yml Wyświetl plik

@@ -104,7 +104,7 @@ jobs:


- name: Run Tests
run: cd ~/frappe-bench/ && bench --site test_site run-tests --app hrms --coverage
run: cd ~/xhiveframework-bench/ && bench --site test_site run-tests --app hrms --coverage
env:
TYPE: server

@@ -112,5 +112,5 @@ jobs:
uses: codecov/codecov-action@v2
with:
fail_ci_if_error: true
files: /home/runner/frappe-bench/sites/coverage.xml
verbose: true
files: /home/runner/xhiveframework-bench/sites/coverage.xml
verbose: true

+ 2
- 2
.github/workflows/linters.yml Wyświetl plik

@@ -20,10 +20,10 @@ jobs:
uses: pre-commit/action@v2.0.3

- name: Download Semgrep rules
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
run: git clone --depth 1 https://github.com/xhiveframework/semgrep-rules.git xhiveframework-semgrep-rules

- name: Download semgrep
run: pip install semgrep==0.97.0

- name: Run Semgrep rules
run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness
run: semgrep ci --config ./xhiveframework-semgrep-rules/rules --config r/python.lang.correctness

+ 4
- 4
.github/workflows/on_release.yml Wyświetl plik

@@ -25,8 +25,8 @@ jobs:
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GIT_AUTHOR_NAME: "Frappe PR Bot"
GIT_AUTHOR_EMAIL: "developers@frappe.io"
GIT_COMMITTER_NAME: "Frappe PR Bot"
GIT_COMMITTER_EMAIL: "developers@frappe.io"
GIT_AUTHOR_NAME: "Xhiveframework PR Bot"
GIT_AUTHOR_EMAIL: "developers@xhiveframework.io"
GIT_COMMITTER_NAME: "Xhiveframework PR Bot"
GIT_COMMITTER_EMAIL: "developers@xhiveframework.io"
run: npx semantic-release

+ 1
- 1
.mergify.yml Wyświetl plik

@@ -4,7 +4,7 @@ pull_request_rules:
- and:
- author!=ruchamahabal
- author!=saurabh6790
- author!=frappe-pr-bot
- author!=xhiveframework-pr-bot
- author!=mergify[bot]
- base=version-14
actions:


+ 14
- 14
README.md Wyświetl plik

@@ -1,19 +1,19 @@
<div align="center" markdown="1">
<img src=".github/frappe-hr-logo.png" alt="Frappe HR logo" width="170" style="max-width: 100%;"/>
<img src=".github/xhiveframework-hr-logo.png" alt="Xhiveframework HR logo" width="170" style="max-width: 100%;"/>

Open Source, modern, and easy-to-use HR and Payroll Software for all organizations.

[![CI](https://github.com/frappe/hrms/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/frappe/hrms/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/frappe/hrms/branch/develop/graph/badge.svg?token=0TwvyUg3I5)](https://codecov.io/gh/frappe/hrms)
[![CI](https://github.com/xhiveframework/hrms/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/xhiveframework/hrms/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/xhiveframework/hrms/branch/develop/graph/badge.svg?token=0TwvyUg3I5)](https://codecov.io/gh/xhiveframework/hrms)


[https://frappehr.com](https://frappehr.com)
[https://xhiveframeworkhr.com](https://xhiveframeworkhr.com)

</div>

## Introduction

Frappe HR has everything you need to drive excellence within the company. It's a complete HRMS solution with over 13 different modules right from Employee Management, Onboarding, Leaves, to Payroll, Taxation, and more!
Xhiveframework HR has everything you need to drive excellence within the company. It's a complete HRMS solution with over 13 different modules right from Employee Management, Onboarding, Leaves, to Payroll, Taxation, and more!

![HRMS](hrms.png)

@@ -35,9 +35,9 @@ Frappe HR has everything you need to drive excellence within the company. It's a

## Installation

1. [Install bench](https://github.com/frappe/bench).
2. [Install ERPNext](https://github.com/frappe/bench#installation).
3. Once ERPNext is installed, add the hrms app to your bench by running
1. [Install bench](https://github.com/xhiveframework/bench).
2. [Install XhiveERP](https://github.com/xhiveframework/bench#installation).
3. Once XhiveERP is installed, add the hrms app to your bench by running

```sh
$ bench get-app hrms
@@ -50,17 +50,17 @@ Frappe HR has everything you need to drive excellence within the company. It's a

## Learning and Community

1. [Documentation](https://frappehr.com/docs) - Extensive documentation for Frappe HR.
2. [User Forum](https://discuss.erpnext.com/) - Engage with the community of ERPNext users and service providers.
3. [Telegram Group](https://t.me/frappehr) - Get instant help from the community of users.
1. [Documentation](https://xhiveframeworkhr.com/docs) - Extensive documentation for Xhiveframework HR.
2. [User Forum](https://discuss.xhiveerp.com/) - Engage with the community of XhiveERP users and service providers.
3. [Telegram Group](https://t.me/xhiveframeworkhr) - Get instant help from the community of users.

## Contribute

1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines) - [Create an issue](https://github.com/frappe/hrms/issues/new)
1. [Contribution Guidelines](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
1. [Issue Guidelines](https://github.com/xhiveframework/xhiveerp/wiki/Issue-Guidelines) - [Create an issue](https://github.com/xhiveframework/hrms/issues/new)
1. [Contribution Guidelines](https://github.com/xhiveframework/xhiveerp/wiki/Contribution-Guidelines)

## License

GNU GPL V3. (See [license.txt](license.txt) for more information).

The HR code is licensed as GNU General Public License (v3) and the copyright is owned by Frappe Technologies Pvt Ltd (Frappe) and Contributors.
The HR code is licensed as GNU General Public License (v3) and the copyright is owned by Xhive LLC Pvt Ltd (Xhiveframework) and Contributors.

+ 1
- 1
hrms/config/desktop.py Wyświetl plik

@@ -1,4 +1,4 @@
from frappe import _
from xhiveframework import _


def get_data():


+ 23
- 23
hrms/controllers/employee_boarding_controller.py Wyświetl plik

@@ -1,14 +1,14 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2021, Xhive LLC
# License: GNU General Public License v3. See license.txt

import frappe
from frappe import _
from frappe.desk.form import assign_to
from frappe.model.document import Document
from frappe.utils import add_days, flt, unique
import xhiveframework
from xhiveframework import _
from xhiveframework.desk.form import assign_to
from xhiveframework.model.document import Document
from xhiveframework.utils import add_days, flt, unique

from erpnext.setup.doctype.employee.employee import get_holiday_list_for_employee
from erpnext.setup.doctype.holiday_list.holiday_list import is_holiday
from xhiveerp.setup.doctype.employee.employee import get_holiday_list_for_employee
from xhiveerp.setup.doctype.holiday_list.holiday_list import is_holiday


class EmployeeBoardingController(Document):
@@ -31,7 +31,7 @@ class EmployeeBoardingController(Document):
else:
project_name += self.employee

project = frappe.get_doc(
project = xhiveframework.get_doc(
{
"doctype": "Project",
"project_name": project_name,
@@ -58,7 +58,7 @@ class EmployeeBoardingController(Document):

dates = self.get_task_dates(activity, holiday_list)

task = frappe.get_doc(
task = xhiveframework.get_doc(
{
"doctype": "Task",
"project": self.project,
@@ -75,7 +75,7 @@ class EmployeeBoardingController(Document):

users = [activity.user] if activity.user else []
if activity.role:
user_list = frappe.db.sql_list(
user_list = xhiveframework.db.sql_list(
"""
SELECT
DISTINCT(has_role.parent)
@@ -107,7 +107,7 @@ class EmployeeBoardingController(Document):
return get_holiday_list_for_employee(self.employee)
else:
if not self.holiday_list:
frappe.throw(_("Please set the Holiday List."), frappe.MandatoryError)
xhiveframework.throw(_("Please set the Holiday List."), xhiveframework.MandatoryError)
else:
return self.holiday_list

@@ -143,21 +143,21 @@ class EmployeeBoardingController(Document):
def on_cancel(self):
# delete task project
project = self.project
for task in frappe.get_all("Task", filters={"project": project}):
frappe.delete_doc("Task", task.name, force=1)
frappe.delete_doc("Project", project, force=1)
for task in xhiveframework.get_all("Task", filters={"project": project}):
xhiveframework.delete_doc("Task", task.name, force=1)
xhiveframework.delete_doc("Project", project, force=1)
self.db_set("project", "")
for activity in self.activities:
activity.db_set("task", "")

frappe.msgprint(
xhiveframework.msgprint(
_("Linked Project {} and Tasks deleted.").format(project), alert=True, indicator="blue"
)


@frappe.whitelist()
@xhiveframework.whitelist()
def get_onboarding_details(parent, parenttype):
return frappe.get_all(
return xhiveframework.get_all(
"Employee Boarding Activity",
fields=[
"activity_name",
@@ -175,8 +175,8 @@ def get_onboarding_details(parent, parenttype):


def update_employee_boarding_status(project, event=None):
employee_onboarding = frappe.db.exists("Employee Onboarding", {"project": project.name})
employee_separation = frappe.db.exists("Employee Separation", {"project": project.name})
employee_onboarding = xhiveframework.db.exists("Employee Onboarding", {"project": project.name})
employee_separation = xhiveframework.db.exists("Employee Separation", {"project": project.name})

if not (employee_onboarding or employee_separation):
return
@@ -188,11 +188,11 @@ def update_employee_boarding_status(project, event=None):
status = "Completed"

if employee_onboarding:
frappe.db.set_value("Employee Onboarding", employee_onboarding, "boarding_status", status)
xhiveframework.db.set_value("Employee Onboarding", employee_onboarding, "boarding_status", status)
elif employee_separation:
frappe.db.set_value("Employee Separation", employee_separation, "boarding_status", status)
xhiveframework.db.set_value("Employee Separation", employee_separation, "boarding_status", status)


def update_task(task, event=None):
if task.project and not task.flags.from_project:
update_employee_boarding_status(frappe.get_cached_doc("Project", task.project))
update_employee_boarding_status(xhiveframework.get_cached_doc("Project", task.project))

+ 21
- 21
hrms/controllers/employee_reminders.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2021, Xhive LLC
# License: GNU General Public License v3. See license.txt

import frappe
from frappe import _
from frappe.utils import add_days, add_months, comma_sep, getdate, today
import xhiveframework
from xhiveframework import _
from xhiveframework.utils import add_days, add_months, comma_sep, getdate, today

from erpnext.setup.doctype.employee.employee import get_all_employee_emails, get_employee_email
from xhiveerp.setup.doctype.employee.employee import get_all_employee_emails, get_employee_email

from hrms.hr.utils import get_holidays_for_employee

@@ -14,8 +14,8 @@ from hrms.hr.utils import get_holidays_for_employee
# HOLIDAY REMINDERS
# -----------------
def send_reminders_in_advance_weekly():
to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders"))
frequency = frappe.db.get_single_value("HR Settings", "frequency")
to_send_in_advance = int(xhiveframework.db.get_single_value("HR Settings", "send_holiday_reminders"))
frequency = xhiveframework.db.get_single_value("HR Settings", "frequency")
if not (to_send_in_advance and frequency == "Weekly"):
return

@@ -23,8 +23,8 @@ def send_reminders_in_advance_weekly():


def send_reminders_in_advance_monthly():
to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders"))
frequency = frappe.db.get_single_value("HR Settings", "frequency")
to_send_in_advance = int(xhiveframework.db.get_single_value("HR Settings", "send_holiday_reminders"))
frequency = xhiveframework.db.get_single_value("HR Settings", "frequency")
if not (to_send_in_advance and frequency == "Monthly"):
return

@@ -45,7 +45,7 @@ def send_advance_holiday_reminders(frequency):
else:
return

employees = frappe.db.get_all("Employee", filters={"status": "Active"}, pluck="name")
employees = xhiveframework.db.get_all("Employee", filters={"status": "Active"}, pluck="name")
for employee in employees:
holidays = get_holidays_for_employee(
employee, start_date, end_date, only_non_weekly=True, raise_exception=False
@@ -58,12 +58,12 @@ def send_holidays_reminder_in_advance(employee, holidays):
if not holidays:
return

employee_doc = frappe.get_doc("Employee", employee)
employee_doc = xhiveframework.get_doc("Employee", employee)
employee_email = get_employee_email(employee_doc)
frequency = frappe.db.get_single_value("HR Settings", "frequency")
frequency = xhiveframework.db.get_single_value("HR Settings", "frequency")

email_header = _("Holidays this Month.") if frequency == "Monthly" else _("Holidays this Week.")
frappe.sendmail(
xhiveframework.sendmail(
recipients=[employee_email],
subject=_("Upcoming Holidays Reminder"),
template="holiday_reminder",
@@ -85,7 +85,7 @@ def send_holidays_reminder_in_advance(employee, holidays):
# ------------------
def send_birthday_reminders():
"""Send Employee birthday reminders if no 'Stop Birthday Reminders' is not set."""
to_send = int(frappe.db.get_single_value("HR Settings", "send_birthday_reminders"))
to_send = int(xhiveframework.db.get_single_value("HR Settings", "send_birthday_reminders"))
if not to_send:
return

@@ -114,7 +114,7 @@ def get_birthday_reminder_text_and_message(birthday_persons):
else:
# converts ["Jim", "Rim", "Dim"] to Jim, Rim & Dim
person_names = [d["name"] for d in birthday_persons]
birthday_person_text = comma_sep(person_names, frappe._("{0} & {1}"), False)
birthday_person_text = comma_sep(person_names, xhiveframework._("{0} & {1}"), False)

reminder_text = _("Today is {0}'s birthday 🎉").format(birthday_person_text)
message = _("A friendly reminder of an important date for our team.")
@@ -125,7 +125,7 @@ def get_birthday_reminder_text_and_message(birthday_persons):


def send_birthday_reminder(recipients, reminder_text, birthday_persons, message):
frappe.sendmail(
xhiveframework.sendmail(
recipients=recipients,
subject=_("Birthday Reminder"),
template="birthday_reminder",
@@ -158,7 +158,7 @@ def get_employees_having_an_event_today(event_type):
else:
return

employees_born_today = frappe.db.multisql(
employees_born_today = xhiveframework.db.multisql(
{
"mariadb": f"""
SELECT `personal_email`, `company`, `company_email`, `user_id`, `employee_name` AS 'name', `image`, `date_of_joining`
@@ -202,7 +202,7 @@ def get_employees_having_an_event_today(event_type):
# --------------------------
def send_work_anniversary_reminders():
"""Send Employee Work Anniversary Reminders if 'Send Work Anniversary Reminders' is checked"""
to_send = int(frappe.db.get_single_value("HR Settings", "send_work_anniversary_reminders"))
to_send = int(xhiveframework.db.get_single_value("HR Settings", "send_work_anniversary_reminders"))
if not to_send:
return

@@ -244,8 +244,8 @@ def get_work_anniversary_reminder_text_and_message(anniversary_persons):
person_names_with_years.append(person_text)

# converts ["Jim", "Rim", "Dim"] to Jim, Rim & Dim
anniversary_person = comma_sep(person_names_with_years, frappe._("{0} & {1}"), False)
persons_name = comma_sep(names, frappe._("{0} & {1}"), False)
anniversary_person = comma_sep(person_names_with_years, xhiveframework._("{0} & {1}"), False)
persons_name = comma_sep(names, xhiveframework._("{0} & {1}"), False)

reminder_text = _("Today {0} at our Company! 🎉").format(anniversary_person)
message = _("A friendly reminder of an important date for our team.")
@@ -262,7 +262,7 @@ def get_pluralized_years(years):


def send_work_anniversary_reminder(recipients, reminder_text, anniversary_persons, message):
frappe.sendmail(
xhiveframework.sendmail(
recipients=recipients,
subject=_("Work Anniversary Reminder"),
template="anniversary_reminder",


+ 29
- 29
hrms/controllers/tests/test_employee_reminders.py Wyświetl plik

@@ -1,13 +1,13 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2021, Xhive LLC
# License: GNU General Public License v3. See license.txt

import unittest
from datetime import timedelta

import frappe
from frappe.utils import add_months, getdate
import xhiveframework
from xhiveframework.utils import add_months, getdate

from erpnext.setup.doctype.employee.test_employee import make_employee
from xhiveerp.setup.doctype.employee.test_employee import make_employee

from hrms.controllers.employee_reminders import send_holidays_reminder_in_advance
from hrms.hr.doctype.hr_settings.hr_settings import set_proceed_with_frequency_change
@@ -17,7 +17,7 @@ from hrms.hr.utils import get_holidays_for_employee
class TestEmployeeReminders(unittest.TestCase):
@classmethod
def setUpClass(cls):
from erpnext.setup.doctype.holiday_list.test_holiday_list import make_holiday_list
from xhiveerp.setup.doctype.holiday_list.test_holiday_list import make_holiday_list

# Create a test holiday list
test_holiday_dates = cls.get_test_holiday_dates()
@@ -36,7 +36,7 @@ class TestEmployeeReminders(unittest.TestCase):
)

# Create a test employee
test_employee = frappe.get_doc(
test_employee = xhiveframework.get_doc(
"Employee", make_employee("test@gopher.io", company="_Test Company")
)

@@ -50,7 +50,7 @@ class TestEmployeeReminders(unittest.TestCase):

# Employee without holidays in this month/week
test_employee_2 = make_employee("test@empwithoutholiday.io", company="_Test Company")
test_employee_2 = frappe.get_doc("Employee", test_employee_2)
test_employee_2 = xhiveframework.get_doc("Employee", test_employee_2)

test_holiday_list = make_holiday_list(
"TestHolidayRemindersList2",
@@ -80,11 +80,11 @@ class TestEmployeeReminders(unittest.TestCase):

def setUp(self):
# Clear Email Queue
frappe.db.sql("delete from `tabEmail Queue`")
frappe.db.sql("delete from `tabEmail Queue Recipient`")
xhiveframework.db.sql("delete from `tabEmail Queue`")
xhiveframework.db.sql("delete from `tabEmail Queue Recipient`")

def test_is_holiday(self):
from erpnext.setup.doctype.employee.employee import is_holiday
from xhiveerp.setup.doctype.employee.employee import is_holiday

self.assertTrue(is_holiday(self.test_employee.name))
self.assertTrue(is_holiday(self.test_employee.name, date=self.test_holiday_dates[1]))
@@ -102,10 +102,10 @@ class TestEmployeeReminders(unittest.TestCase):
self.assertTrue("test holiday1" in descriptions)

def test_birthday_reminders(self):
employee = frappe.get_doc(
"Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0]
employee = xhiveframework.get_doc(
"Employee", xhiveframework.db.sql_list("select name from tabEmployee limit 1")[0]
)
employee.date_of_birth = "1992" + frappe.utils.nowdate()[4:]
employee.date_of_birth = "1992" + xhiveframework.utils.nowdate()[4:]
employee.company_email = "test@example.com"
employee.company = "_Test Company"
employee.save()
@@ -118,13 +118,13 @@ class TestEmployeeReminders(unittest.TestCase):
employees_born_today = get_employees_who_are_born_today()
self.assertTrue(employees_born_today.get("_Test Company"))

hr_settings = frappe.get_doc("HR Settings", "HR Settings")
hr_settings = xhiveframework.get_doc("HR Settings", "HR Settings")
hr_settings.send_birthday_reminders = 1
hr_settings.save()

send_birthday_reminders()

email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
email_queue = xhiveframework.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertTrue("Subject: Birthday Reminder" in email_queue[0].message)

def test_work_anniversary_reminders(self):
@@ -136,7 +136,7 @@ class TestEmployeeReminders(unittest.TestCase):
emp = make_employee(
"test_emp_work_anniversary@gmail.com",
company="_Test Company",
date_of_joining=frappe.utils.add_years(getdate(), -2),
date_of_joining=xhiveframework.utils.add_years(getdate(), -2),
)

employees_having_work_anniversary = get_employees_having_an_event_today("work_anniversary")
@@ -147,13 +147,13 @@ class TestEmployeeReminders(unittest.TestCase):

self.assertTrue("test_emp_work_anniversary@gmail.com" in user_ids)

hr_settings = frappe.get_doc("HR Settings", "HR Settings")
hr_settings = xhiveframework.get_doc("HR Settings", "HR Settings")
hr_settings.send_work_anniversary_reminders = 1
hr_settings.save()

send_work_anniversary_reminders()

email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
email_queue = xhiveframework.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertTrue("Subject: Work Anniversary Reminder" in email_queue[0].message)

def test_work_anniversary_reminder_not_sent_for_0_years(self):
@@ -186,7 +186,7 @@ class TestEmployeeReminders(unittest.TestCase):

send_holidays_reminder_in_advance(self.test_employee.get("name"), holidays)

email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
email_queue = xhiveframework.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertEqual(len(email_queue), 1)
self.assertTrue("Holidays this Week." in email_queue[0].message)

@@ -196,22 +196,22 @@ class TestEmployeeReminders(unittest.TestCase):
setup_hr_settings("Monthly")

# disable emp 2, set same holiday list
frappe.db.set_value(
xhiveframework.db.set_value(
"Employee",
self.test_employee_2.name,
{"status": "Left", "holiday_list": self.test_employee.holiday_list},
)

send_reminders_in_advance_monthly()
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
email_queue = xhiveframework.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertTrue(len(email_queue) > 0)

# even though emp 2 has holiday, non-active employees should not be recipients
recipients = frappe.db.get_all("Email Queue Recipient", pluck="recipient")
recipients = xhiveframework.db.get_all("Email Queue Recipient", pluck="recipient")
self.assertTrue(self.test_employee_2.user_id not in recipients)

# teardown: enable emp 2
frappe.db.set_value(
xhiveframework.db.set_value(
"Employee",
self.test_employee_2.name,
{"status": "Active", "holiday_list": self.holiday_list_2.name},
@@ -223,22 +223,22 @@ class TestEmployeeReminders(unittest.TestCase):
setup_hr_settings("Weekly")

# disable emp 2, set same holiday list
frappe.db.set_value(
xhiveframework.db.set_value(
"Employee",
self.test_employee_2.name,
{"status": "Left", "holiday_list": self.test_employee.holiday_list},
)

send_reminders_in_advance_weekly()
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
email_queue = xhiveframework.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertTrue(len(email_queue) > 0)

# even though emp 2 has holiday, non-active employees should not be recipients
recipients = frappe.db.get_all("Email Queue Recipient", pluck="recipient")
recipients = xhiveframework.db.get_all("Email Queue Recipient", pluck="recipient")
self.assertTrue(self.test_employee_2.user_id not in recipients)

# teardown: enable emp 2
frappe.db.set_value(
xhiveframework.db.set_value(
"Employee",
self.test_employee_2.name,
{"status": "Active", "holiday_list": self.holiday_list_2.name},
@@ -256,13 +256,13 @@ class TestEmployeeReminders(unittest.TestCase):
raise_exception=False,
)
send_holidays_reminder_in_advance(self.test_employee_2.get("name"), holidays)
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
email_queue = xhiveframework.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
self.assertEqual(len(email_queue), 0)


def setup_hr_settings(frequency=None):
# Get HR settings and enable advance holiday reminders
hr_settings = frappe.get_doc("HR Settings", "HR Settings")
hr_settings = xhiveframework.get_doc("HR Settings", "HR Settings")
hr_settings.send_holiday_reminders = 1
set_proceed_with_frequency_change()
hr_settings.frequency = frequency or "Weekly"


+ 21
- 21
hrms/hooks.py Wyświetl plik

@@ -1,10 +1,10 @@
app_name = "hrms"
app_title = "Frappe HR"
app_publisher = "Frappe Technologies Pvt. Ltd."
app_title = "Xhiveframework HR"
app_publisher = "Xhive LLC Pvt. Ltd."
app_description = "Modern HR and Payroll Software"
app_email = "contact@frappe.io"
app_email = "contact@xhiveframework.io"
app_license = "GNU General Public License (v3)"
required_apps = ["erpnext"]
required_apps = ["xhiveerp"]


# Includes in <head>
@@ -36,14 +36,14 @@ app_include_css = "hrms.bundle.css"

# include js in doctype views
doctype_js = {
"Employee": "public/js/erpnext/employee.js",
"Company": "public/js/erpnext/company.js",
"Department": "public/js/erpnext/department.js",
"Timesheet": "public/js/erpnext/timesheet.js",
"Payment Entry": "public/js/erpnext/payment_entry.js",
"Journal Entry": "public/js/erpnext/journal_entry.js",
"Delivery Trip": "public/js/erpnext/deliver_trip.js",
"Bank Transaction": "public/js/erpnext/bank_transaction.js",
"Employee": "public/js/xhiveerp/employee.js",
"Company": "public/js/xhiveerp/company.js",
"Department": "public/js/xhiveerp/department.js",
"Timesheet": "public/js/xhiveerp/timesheet.js",
"Payment Entry": "public/js/xhiveerp/payment_entry.js",
"Journal Entry": "public/js/xhiveerp/journal_entry.js",
"Delivery Trip": "public/js/xhiveerp/deliver_trip.js",
"Bank Transaction": "public/js/xhiveerp/bank_transaction.js",
}
# doctype_list_js = {"doctype" : "public/js/doctype_list.js"}
# doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"}
@@ -94,7 +94,7 @@ before_uninstall = "hrms.uninstall.before_uninstall"

# Desk Notifications
# ------------------
# See frappe.core.notifications.get_notification_config
# See xhiveframework.core.notifications.get_notification_config

# notification_config = "hrms.notifications.get_notification_config"

@@ -103,15 +103,15 @@ before_uninstall = "hrms.uninstall.before_uninstall"
# Permissions evaluated in scripted ways

# permission_query_conditions = {
# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions",
# "Event": "xhiveframework.desk.doctype.event.event.get_permission_query_conditions",
# }
#
# has_permission = {
# "Event": "frappe.desk.doctype.event.event.has_permission",
# "Event": "xhiveframework.desk.doctype.event.event.has_permission",
# }

has_upload_permission = {
"Employee": "erpnext.setup.doctype.employee.employee.has_upload_permission"
"Employee": "xhiveerp.setup.doctype.employee.employee.has_upload_permission"
}

# DocType Class
@@ -131,8 +131,8 @@ override_doctype_class = {

doc_events = {
"User": {
"validate": "erpnext.setup.doctype.employee.employee.validate_employee_role",
"on_update": "erpnext.setup.doctype.employee.employee.update_user_permissions",
"validate": "xhiveerp.setup.doctype.employee.employee.validate_employee_role",
"on_update": "xhiveerp.setup.doctype.employee.employee.update_user_permissions",
},
"Company": {
"validate": "hrms.overrides.company.validate_default_accounts",
@@ -233,7 +233,7 @@ regional_overrides = {
},
}

# ERPNext doctypes for Global Search
# XhiveERP doctypes for Global Search
global_search_doctypes = {
"Default": [
{"doctype": "Salary Slip", "index": 19},
@@ -249,12 +249,12 @@ global_search_doctypes = {
}

# override_whitelisted_methods = {
# "frappe.desk.doctype.event.event.get_events": "hrms.event.get_events"
# "xhiveframework.desk.doctype.event.event.get_events": "hrms.event.get_events"
# }
#
# each overriding function accepts a `data` argument;
# generated from the base implementation of the doctype dashboard,
# along with any modifications made in other Frappe apps
# along with any modifications made in other Xhiveframework apps
override_doctype_dashboards = {
"Employee": "hrms.overrides.dashboard_overrides.get_dashboard_for_employee",
"Holiday List": "hrms.overrides.dashboard_overrides.get_dashboard_for_holiday_list",


+ 2
- 2
hrms/hr/dashboard_chart/attendance_count/attendance_count.json Wyświetl plik

@@ -5,7 +5,7 @@
"custom_options": "{\n\t\t\"type\": \"line\",\n\t\t\"axisOptions\": {\n\t\t\t\"shortenYAxisNumbers\": 1\n\t\t},\n\t\t\"tooltipOptions\": {}\n\t}",
"docstatus": 0,
"doctype": "Dashboard Chart",
"dynamic_filters_json": "{\"month\":\"frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth() + 1\",\"year\":\"frappe.datetime.str_to_obj(frappe.datetime.get_today()).getFullYear();\",\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\"}",
"dynamic_filters_json": "{\"month\":\"xhiveframework.datetime.str_to_obj(xhiveframework.datetime.get_today()).getMonth() + 1\",\"year\":\"xhiveframework.datetime.str_to_obj(xhiveframework.datetime.get_today()).getFullYear();\",\"company\":\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"}",
"filters_json": "{\"summarized_view\":0}",
"group_by_type": "Count",
"idx": 0,
@@ -25,4 +25,4 @@
"type": "Line",
"use_report_chart": 1,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/department_wise_employee_count/department_wise_employee_count.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
"group_by_based_on": "department",
"group_by_type": "Count",
@@ -27,4 +27,4 @@
"type": "Pie",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/department_wise_expense_claims/department_wise_expense_claims.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Expense Claim",
"dynamic_filters_json": "[[\"Expense Claim\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Expense Claim\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Expense Claim\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_based_on": "department",
"group_by_type": "Count",
@@ -30,4 +30,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/department_wise_openings/department_wise_openings.json Wyświetl plik

@@ -7,7 +7,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Job Opening",
"dynamic_filters_json": "[[\"Job Opening\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Job Opening\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Job Opening\",\"status\",\"=\",\"Open\",false]]",
"group_by_based_on": "department",
"group_by_type": "Count",
@@ -28,4 +28,4 @@
"type": "Bar",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/department_wise_timesheet_hours/department_wise_timesheet_hours.json Wyświetl plik

@@ -7,7 +7,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Timesheet",
"dynamic_filters_json": "[[\"Timesheet\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Timesheet\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Timesheet\",\"start_date\",\"Timespan\",\"this month\",false],[\"Timesheet\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_based_on": "department",
"group_by_type": "Sum",
@@ -31,4 +31,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/designation_wise_employee_count/designation_wise_employee_count.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
"group_by_based_on": "designation",
"group_by_type": "Count",
@@ -27,4 +27,4 @@
"type": "Pie",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/designation_wise_openings/designation_wise_openings.json Wyświetl plik

@@ -7,7 +7,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Job Opening",
"dynamic_filters_json": "[[\"Job Opening\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Job Opening\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Job Opening\",\"status\",\"=\",\"Open\",false]]",
"group_by_based_on": "designation",
"group_by_type": "Count",
@@ -28,4 +28,4 @@
"type": "Bar",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/employee_advance_status/employee_advance_status.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee Advance",
"dynamic_filters_json": "[[\"Employee Advance\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee Advance\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee Advance\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_based_on": "status",
"group_by_type": "Count",
@@ -30,4 +30,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/employees_by_age/employees_by_age.json Wyświetl plik

@@ -7,7 +7,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\"}",
"dynamic_filters_json": "{\"company\":\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"}",
"filters_json": "{}",
"group_by_type": "Count",
"idx": 0,
@@ -30,4 +30,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/employees_by_branch/employees_by_branch.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
"group_by_based_on": "branch",
"group_by_type": "Count",
@@ -27,4 +27,4 @@
"type": "Pie",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/employees_by_grade/employees_by_grade.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
"group_by_based_on": "grade",
"group_by_type": "Count",
@@ -27,4 +27,4 @@
"type": "Pie",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/employees_by_type/employees_by_type.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
"group_by_based_on": "employment_type",
"group_by_type": "Count",
@@ -27,4 +27,4 @@
"type": "Pie",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/expense_claims/expense_claims.json Wyświetl plik

@@ -7,7 +7,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Expense Claim",
"dynamic_filters_json": "[[\"Expense Claim\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Expense Claim\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Expense Claim\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_type": "Count",
"idx": 0,
@@ -30,4 +30,4 @@
"use_report_chart": 0,
"value_based_on": "total_sanctioned_amount",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/gender_diversity_ratio/gender_diversity_ratio.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
"group_by_based_on": "gender",
"group_by_type": "Count",
@@ -26,4 +26,4 @@
"type": "Pie",
"use_report_chart": 0,
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/grievance_type/grievance_type.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee Grievance",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee Grievance\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_based_on": "grievance_type",
"group_by_type": "Count",
@@ -30,4 +30,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/hiring_vs_attrition_count/hiring_vs_attrition_count.json Wyświetl plik

@@ -7,7 +7,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\", \"from_date\":\"frappe.defaults.get_user_default(\\\"year_start_date\\\")\", \"to_date\":\"frappe.defaults.get_user_default(\\\"year_end_date\\\")\"}",
"dynamic_filters_json": "{\"company\":\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\", \"from_date\":\"xhiveframework.defaults.get_user_default(\\\"year_start_date\\\")\", \"to_date\":\"xhiveframework.defaults.get_user_default(\\\"year_end_date\\\")\"}",
"filters_json": "{\"time_interval\":\"Monthly\"}",
"group_by_type": "Count",
"idx": 0,
@@ -30,4 +30,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/shift_assignment_breakup/shift_assignment_breakup.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Shift Assignment",
"dynamic_filters_json": "[[\"Shift Assignment\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Shift Assignment\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Shift Assignment\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_based_on": "shift_type",
"group_by_type": "Count",
@@ -29,4 +29,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/y_o_y_promotions/y_o_y_promotions.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee Promotion",
"dynamic_filters_json": "[[\"Employee Promotion\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee Promotion\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee Promotion\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_type": "Count",
"idx": 0,
@@ -28,4 +28,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 2
- 2
hrms/hr/dashboard_chart/y_o_y_transfers/y_o_y_transfers.json Wyświetl plik

@@ -6,7 +6,7 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Employee Transfer",
"dynamic_filters_json": "[[\"Employee Transfer\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
"dynamic_filters_json": "[[\"Employee Transfer\",\"company\",\"=\",\"xhiveframework.defaults.get_user_default(\\\"Company\\\")\"]]",
"filters_json": "[[\"Employee Transfer\",\"docstatus\",\"=\",\"1\",false]]",
"group_by_type": "Count",
"idx": 0,
@@ -28,4 +28,4 @@
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}
}

+ 3
- 3
hrms/hr/dashboard_chart_source/employees_by_age/employees_by_age.js Wyświetl plik

@@ -1,6 +1,6 @@
frappe.provide("frappe.dashboards.chart_sources");
xhiveframework.provide("xhiveframework.dashboards.chart_sources");

frappe.dashboards.chart_sources["Employees by Age"] = {
xhiveframework.dashboards.chart_sources["Employees by Age"] = {
method: "hrms.hr.dashboard_chart_source.employees_by_age.employees_by_age.get_data",
filters: [
{
@@ -8,7 +8,7 @@ frappe.dashboards.chart_sources["Employees by Age"] = {
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company")
default: xhiveframework.defaults.get_user_default("Company")
},
]
};

+ 8
- 8
hrms/hr/dashboard_chart_source/employees_by_age/employees_by_age.py Wyświetl plik

@@ -1,16 +1,16 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2022, Xhive LLC
# License: GNU General Public License v3. See license.txt


from dateutil.relativedelta import relativedelta

import frappe
from frappe import _
from frappe.utils import getdate
from frappe.utils.dashboard import cache_source
import xhiveframework
from xhiveframework import _
from xhiveframework.utils import getdate
from xhiveframework.utils.dashboard import cache_source


@frappe.whitelist()
@xhiveframework.whitelist()
@cache_source
def get_data(
chart_name=None,
@@ -24,9 +24,9 @@ def get_data(
heatmap_year=None,
) -> dict[str, list]:
if filters:
filters = frappe.parse_json(filters)
filters = xhiveframework.parse_json(filters)

employees = frappe.db.get_list(
employees = xhiveframework.db.get_list(
"Employee",
filters={"company": filters.get("company"), "status": "Active"},
pluck="date_of_birth",


+ 5
- 5
hrms/hr/dashboard_chart_source/hiring_vs_attrition_count/hiring_vs_attrition_count.js Wyświetl plik

@@ -1,6 +1,6 @@
frappe.provide("frappe.dashboards.chart_sources");
xhiveframework.provide("xhiveframework.dashboards.chart_sources");

frappe.dashboards.chart_sources["Hiring vs Attrition Count"] = {
xhiveframework.dashboards.chart_sources["Hiring vs Attrition Count"] = {
method: "hrms.hr.dashboard_chart_source.hiring_vs_attrition_count.hiring_vs_attrition_count.get_data",
filters: [
{
@@ -8,20 +8,20 @@ frappe.dashboards.chart_sources["Hiring vs Attrition Count"] = {
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company")
default: xhiveframework.defaults.get_user_default("Company")
},
{
fieldname: "from_date",
label: __("From Date"),
fieldtype: "Date",
default: frappe.defaults.get_user_default("year_start_date"),
default: xhiveframework.defaults.get_user_default("year_start_date"),
reqd: 1,
},
{
fieldname: "to_date",
label: __("To Date"),
fieldtype: "Date",
default: frappe.defaults.get_user_default("year_end_date"),
default: xhiveframework.defaults.get_user_default("year_end_date"),
},
{
fieldname: "time_interval",


+ 10
- 10
hrms/hr/dashboard_chart_source/hiring_vs_attrition_count/hiring_vs_attrition_count.py Wyświetl plik

@@ -1,16 +1,16 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2022, Xhive LLC
# License: GNU General Public License v3. See license.txt


import frappe
from frappe import _
from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_result
from frappe.utils import getdate
from frappe.utils.dashboard import cache_source
from frappe.utils.dateutils import get_period
import xhiveframework
from xhiveframework import _
from xhiveframework.desk.doctype.dashboard_chart.dashboard_chart import get_result
from xhiveframework.utils import getdate
from xhiveframework.utils.dashboard import cache_source
from xhiveframework.utils.dateutils import get_period


@frappe.whitelist()
@xhiveframework.whitelist()
@cache_source
def get_data(
chart_name=None,
@@ -24,7 +24,7 @@ def get_data(
heatmap_year=None,
) -> dict[str, list]:
if filters:
filters = frappe.parse_json(filters)
filters = xhiveframework.parse_json(filters)

from_date = filters.get("from_date")
to_date = filters.get("to_date")
@@ -56,7 +56,7 @@ def get_records(
["Employee", datefield, "<=", to_date, False],
]

data = frappe.db.get_list(
data = xhiveframework.db.get_list(
"Employee",
fields=[f"{datefield} as _unit", "SUM(1)", "COUNT(*)"],
filters=filters,


+ 3
- 3
hrms/hr/doctype/appointment_letter/appointment_letter.js Wyświetl plik

@@ -1,10 +1,10 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2019, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Appointment Letter', {
xhiveframework.ui.form.on('Appointment Letter', {
appointment_letter_template: function(frm){
if (frm.doc.appointment_letter_template){
frappe.call({
xhiveframework.call({
method: 'hrms.hr.doctype.appointment_letter.appointment_letter.get_appointment_letter_details',
args : {
template : frm.doc.appointment_letter_template


+ 6
- 6
hrms/hr/doctype/appointment_letter/appointment_letter.py Wyświetl plik

@@ -1,24 +1,24 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2019, Xhive LLC
# For license information, please see license.txt


import frappe
from frappe.model.document import Document
import xhiveframework
from xhiveframework.model.document import Document


class AppointmentLetter(Document):
pass


@frappe.whitelist()
@xhiveframework.whitelist()
def get_appointment_letter_details(template):
body = []
intro = frappe.get_list(
intro = xhiveframework.get_list(
"Appointment Letter Template",
fields=["introduction", "closing_notes"],
filters={"name": template},
)[0]
content = frappe.get_all(
content = xhiveframework.get_all(
"Appointment Letter content",
fields=["title", "description"],
filters={"parent": template},


+ 2
- 2
hrms/hr/doctype/appointment_letter/test_appointment_letter.py Wyświetl plik

@@ -1,7 +1,7 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2019, Xhive LLC
# See license.txt

# import frappe
# import xhiveframework
import unittest




+ 3
- 3
hrms/hr/doctype/appointment_letter_content/appointment_letter_content.py Wyświetl plik

@@ -1,9 +1,9 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2019, Xhive LLC
# For license information, please see license.txt


# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class AppointmentLettercontent(Document):


+ 2
- 2
hrms/hr/doctype/appointment_letter_template/appointment_letter_template.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2019, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Appointment Letter Template', {
xhiveframework.ui.form.on('Appointment Letter Template', {
// refresh: function(frm) {

// }


+ 3
- 3
hrms/hr/doctype/appointment_letter_template/appointment_letter_template.py Wyświetl plik

@@ -1,9 +1,9 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2019, Xhive LLC
# For license information, please see license.txt


# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class AppointmentLetterTemplate(Document):


+ 2
- 2
hrms/hr/doctype/appointment_letter_template/test_appointment_letter_template.py Wyświetl plik

@@ -1,7 +1,7 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2019, Xhive LLC
# See license.txt

# import frappe
# import xhiveframework
import unittest




+ 13
- 13
hrms/hr/doctype/appraisal/appraisal.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// Copyright (c) 2015, Xhive LLC
// License: GNU General Public License v3. See license.txt

frappe.ui.form.on("Appraisal", {
xhiveframework.ui.form.on("Appraisal", {
refresh(frm) {
if (!frm.doc.__islocal) {
frm.trigger("add_custom_buttons");
@@ -24,10 +24,10 @@ frappe.ui.form.on("Appraisal", {

appraisal_cycle(frm) {
if (frm.doc.appraisal_cycle) {
frappe.run_serially([
xhiveframework.run_serially([
() => {
if (frm.doc.__islocal && frm.doc.appraisal_cycle) {
frappe.db.get_value("Appraisal Cycle", frm.doc.appraisal_cycle, "kra_evaluation_method", (r) => {
xhiveframework.db.get_value("Appraisal Cycle", frm.doc.appraisal_cycle, "kra_evaluation_method", (r) => {
if (r.kra_evaluation_method) {
frm.set_value("rate_goals_manually", cint(r.kra_evaluation_method === "Manual Rating"));
}
@@ -46,17 +46,17 @@ frappe.ui.form.on("Appraisal", {

add_custom_buttons(frm) {
frm.add_custom_button(__("View Goals"), function() {
frappe.route_options = {
xhiveframework.route_options = {
company: frm.doc.company,
employee: frm.doc.employee,
appraisal_cycle: frm.doc.appraisal_cycle,
};
frappe.set_route("Tree", "Goal");
xhiveframework.set_route("Tree", "Goal");
});
},

show_feedback_history(frm) {
frappe.require("performance.bundle.js", () => {
xhiveframework.require("performance.bundle.js", () => {
const feedback_history = new hrms.PerformanceFeedback({
frm: frm,
wrapper: $(frm.fields_dict.feedback_html.wrapper),
@@ -116,12 +116,12 @@ frappe.ui.form.on("Appraisal", {
});


frappe.ui.form.on("Appraisal Goal", {
xhiveframework.ui.form.on("Appraisal Goal", {
score(frm, cdt, cdn) {
let d = frappe.get_doc(cdt, cdn);
let d = xhiveframework.get_doc(cdt, cdn);

if (flt(d.score) > 5) {
frappe.msgprint(__("Score must be less than or equal to 5"));
xhiveframework.msgprint(__("Score must be less than or equal to 5"));
d.score = 0;
refresh_field("score", d.name, "goals");
} else {
@@ -138,11 +138,11 @@ frappe.ui.form.on("Appraisal Goal", {
},

set_score_earned(frm, cdt, cdn) {
let d = frappe.get_doc(cdt, cdn);
let d = xhiveframework.get_doc(cdt, cdn);

score_earned = flt(d.score) * flt(d.per_weightage) / 100;
frappe.model.set_value(cdt, cdn, "score_earned", score_earned);
xhiveframework.model.set_value(cdt, cdn, "score_earned", score_earned);

frm.trigger("calculate_total");
}
});
});

+ 34
- 34
hrms/hr/doctype/appraisal/appraisal.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhive LLC
# License: GNU General Public License v3. See license.txt

import frappe
from frappe import _
from frappe.model.document import Document
from frappe.query_builder.functions import Avg
from frappe.utils import flt, get_link_to_form, now
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.query_builder.functions import Avg
from xhiveframework.utils import flt, get_link_to_form, now

from hrms.hr.doctype.appraisal_cycle.appraisal_cycle import validate_active_appraisal_cycle
from hrms.hr.utils import validate_active_employee
@@ -28,9 +28,9 @@ class Appraisal(Document):
self.calculate_final_score()

def validate_duplicate(self):
Appraisal = frappe.qb.DocType("Appraisal")
Appraisal = xhiveframework.qb.DocType("Appraisal")
duplicate = (
frappe.qb.from_(Appraisal)
xhiveframework.qb.from_(Appraisal)
.select(Appraisal.name)
.where(
(Appraisal.employee == self.employee)
@@ -50,13 +50,13 @@ class Appraisal(Document):
duplicate = duplicate[0][0] if duplicate else 0

if duplicate:
frappe.throw(
xhiveframework.throw(
_(
"Appraisal {0} already exists for Employee {1} for this Appraisal Cycle or overlapping period"
).format(
get_link_to_form("Appraisal", duplicate), frappe.bold(self.employee_name)
get_link_to_form("Appraisal", duplicate), xhiveframework.bold(self.employee_name)
),
exc=frappe.DuplicateEntryError,
exc=xhiveframework.DuplicateEntryError,
title=_("Duplicate Entry"),
)

@@ -65,19 +65,19 @@ class Appraisal(Document):
self.is_new()
and self.appraisal_cycle
and (
frappe.db.get_value("Appraisal Cycle", self.appraisal_cycle, "kra_evaluation_method")
xhiveframework.db.get_value("Appraisal Cycle", self.appraisal_cycle, "kra_evaluation_method")
== "Manual Rating"
)
):
self.rate_goals_manually = 1

@frappe.whitelist()
@xhiveframework.whitelist()
def set_appraisal_template(self):
"""Sets appraisal template from Appraisee table in Cycle"""
if not self.appraisal_cycle:
return

appraisal_template = frappe.db.get_value(
appraisal_template = xhiveframework.db.get_value(
"Appraisee",
{
"employee": self.employee,
@@ -90,7 +90,7 @@ class Appraisal(Document):
self.appraisal_template = appraisal_template
self.set_kras_and_rating_criteria()

@frappe.whitelist()
@xhiveframework.whitelist()
def set_kras_and_rating_criteria(self):
if not self.appraisal_template:
return
@@ -99,7 +99,7 @@ class Appraisal(Document):
self.set("self_ratings", [])
self.set("goals", [])

template = frappe.get_doc("Appraisal Template", self.appraisal_template)
template = xhiveframework.get_doc("Appraisal Template", self.appraisal_template)

for entry in template.goals:
table_name = "goals" if self.rate_goals_manually else "appraisal_kra"
@@ -130,7 +130,7 @@ class Appraisal(Document):
table = _("Goals")
for entry in self.goals:
if flt(entry.score) > 5:
frappe.throw(_("Row {0}: Goal Score cannot be greater than 5").format(entry.idx))
xhiveframework.throw(_("Row {0}: Goal Score cannot be greater than 5").format(entry.idx))

entry.score_earned = flt(entry.score) * flt(entry.per_weightage) / 100
total += flt(entry.score_earned)
@@ -147,7 +147,7 @@ class Appraisal(Document):
total = flt(goal_score_percentage) / 20

if total_weightage and flt(total_weightage, 2) != 100.0:
frappe.throw(
xhiveframework.throw(
_("Total weightage for all {0} must add up to 100. Currently, it is {1}%").format(
table, total_weightage
),
@@ -165,7 +165,7 @@ class Appraisal(Document):
self.self_score = flt(total, self.precision("self_score"))

def calculate_avg_feedback_score(self, update=False):
avg_feedback_score = frappe.qb.avg(
avg_feedback_score = xhiveframework.qb.avg(
"Employee Performance Feedback",
"total_score",
{"employee": self.employee, "appraisal": self.name, "docstatus": 1},
@@ -182,16 +182,16 @@ class Appraisal(Document):

self.final_score = flt(final_score, self.precision("final_score"))

@frappe.whitelist()
@xhiveframework.whitelist()
def add_feedback(self, feedback, feedback_ratings):
feedback = frappe.get_doc(
feedback = xhiveframework.get_doc(
{
"doctype": "Employee Performance Feedback",
"appraisal": self.name,
"employee": self.employee,
"added_on": now(),
"feedback": feedback,
"reviewer": frappe.db.get_value("Employee", {"user_id": frappe.session.user}),
"reviewer": xhiveframework.db.get_value("Employee", {"user_id": xhiveframework.session.user}),
}
)

@@ -212,9 +212,9 @@ class Appraisal(Document):
def set_goal_score(self, update=False):
for kra in self.appraisal_kra:
# update progress for all goals as KRA linked could be removed or changed
Goal = frappe.qb.DocType("Goal")
Goal = xhiveframework.qb.DocType("Goal")
avg_goal_completion = (
frappe.qb.from_(Goal)
xhiveframework.qb.from_(Goal)
.select(Avg(Goal.progress).as_("avg_goal_completion"))
.where(
(Goal.kra == kra.kra)
@@ -241,10 +241,10 @@ class Appraisal(Document):
return self


@frappe.whitelist()
@xhiveframework.whitelist()
def get_feedback_history(employee, appraisal):
data = frappe._dict()
data.feedback_history = frappe.get_list(
data = xhiveframework._dict()
data.feedback_history = xhiveframework.get_list(
"Employee Performance Feedback",
filters={"employee": employee, "appraisal": appraisal, "docstatus": 1},
fields=[
@@ -265,7 +265,7 @@ def get_feedback_history(employee, appraisal):
# get percentage of reviews per rating
reviews_per_rating = []

feedback_count = frappe.db.count(
feedback_count = xhiveframework.db.count(
"Employee Performance Feedback",
filters={
"appraisal": appraisal,
@@ -275,7 +275,7 @@ def get_feedback_history(employee, appraisal):
)

for i in range(1, 6):
count = frappe.db.count(
count = xhiveframework.db.count(
"Employee Performance Feedback",
filters={
"appraisal": appraisal,
@@ -289,15 +289,15 @@ def get_feedback_history(employee, appraisal):
reviews_per_rating.append(percent)

data.reviews_per_rating = reviews_per_rating
data.avg_feedback_score = frappe.db.get_value("Appraisal", appraisal, "avg_feedback_score")
data.avg_feedback_score = xhiveframework.db.get_value("Appraisal", appraisal, "avg_feedback_score")

return data


@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
@xhiveframework.whitelist()
@xhiveframework.validate_and_sanitize_search_inputs
def get_kras_for_employee(doctype, txt, searchfield, start, page_len, filters):
appraisal = frappe.db.get_value(
appraisal = xhiveframework.db.get_value(
"Appraisal",
{
"appraisal_cycle": filters.get("appraisal_cycle"),
@@ -306,7 +306,7 @@ def get_kras_for_employee(doctype, txt, searchfield, start, page_len, filters):
"name",
)

return frappe.get_all(
return xhiveframework.get_all(
"Appraisal KRA",
filters={"parent": appraisal, "kra": ("like", "{0}%".format(txt))},
fields=["kra"],


+ 32
- 32
hrms/hr/doctype/appraisal/test_appraisal.py Wyświetl plik

@@ -1,13 +1,13 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors
# Copyright (c) 2015, Xhive LLC and Contributors
# See license.txt

import unittest

import frappe
from frappe.tests.utils import FrappeTestCase
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase

from erpnext.setup.doctype.designation.test_designation import create_designation
from erpnext.setup.doctype.employee.test_employee import make_employee
from xhiveerp.setup.doctype.designation.test_designation import create_designation
from xhiveerp.setup.doctype.employee.test_employee import make_employee

from hrms.hr.doctype.appraisal_cycle.appraisal_cycle import get_appraisal_cycle_summary
from hrms.hr.doctype.appraisal_cycle.test_appraisal_cycle import create_appraisal_cycle
@@ -19,11 +19,11 @@ from hrms.hr.doctype.goal.test_goal import create_goal
from hrms.tests.test_utils import create_company


class TestAppraisal(FrappeTestCase):
class TestAppraisal(XhiveframeworkTestCase):
def setUp(self):
frappe.db.delete("Goal")
frappe.db.delete("Appraisal")
frappe.db.delete("Employee Performance Feedback")
xhiveframework.db.delete("Goal")
xhiveframework.db.delete("Appraisal")
xhiveframework.db.delete("Employee Performance Feedback")

self.company = create_company("_Test Appraisal").name
self.template = create_appraisal_template()
@@ -40,7 +40,7 @@ class TestAppraisal(FrappeTestCase):
cycle = create_appraisal_cycle(designation="Engineer")
cycle.create_appraisals()

appraisal = frappe.get_doc(
appraisal = xhiveframework.get_doc(
{
"doctype": "Appraisal",
"employee": self.employee1,
@@ -49,16 +49,16 @@ class TestAppraisal(FrappeTestCase):
)
appraisal.set_appraisal_template()

self.assertRaises(frappe.DuplicateEntryError, appraisal.insert)
self.assertRaises(xhiveframework.DuplicateEntryError, appraisal.insert)

def test_manual_kra_rating(self):
cycle = create_appraisal_cycle(designation="Engineer", kra_evaluation_method="Manual Rating")
cycle.create_appraisals()

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

# 30% weightage
appraisal.goals[0].score = 5
@@ -76,10 +76,10 @@ class TestAppraisal(FrappeTestCase):
cycle = create_appraisal_cycle(designation="Engineer", kra_evaluation_method="Manual Rating")
cycle.create_appraisals()

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

# GOAL SCORE
appraisal.goals[0].score = 5 # 30% weightage
@@ -130,10 +130,10 @@ class TestAppraisal(FrappeTestCase):
child2_1 = create_goal(self.employee1, parent_goal=parent2.name, progress=100)
child2_2 = create_goal(self.employee1, parent_goal=parent2.name)

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

# Quality KRA, 30% weightage
self.assertEqual(appraisal.appraisal_kra[0].goal_completion, 12.5)
@@ -175,10 +175,10 @@ class TestAppraisal(FrappeTestCase):
child2_1 = create_goal(self.employee1, parent_goal=parent2.name, progress=50)
child2_2 = create_goal(self.employee1, parent_goal=parent2.name)

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

# Quality KRA, 30% weightage
self.assertEqual(appraisal.appraisal_kra[0].goal_completion, 50)
@@ -207,10 +207,10 @@ class TestAppraisal(FrappeTestCase):

goal = create_goal(self.employee1, "Quality", appraisal_cycle=cycle.name, progress=50)

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

# Quality KRA, 30% weightage
self.assertEqual(appraisal.appraisal_kra[0].goal_completion, 50)
@@ -233,10 +233,10 @@ class TestAppraisal(FrappeTestCase):

goal = create_goal(self.employee1, "Quality", appraisal_cycle=cycle.name, progress=50)

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

# Quality KRA, 30% weightage
self.assertEqual(appraisal.appraisal_kra[0].goal_completion, 50)
@@ -251,10 +251,10 @@ class TestAppraisal(FrappeTestCase):
cycle = create_appraisal_cycle(designation="Engineer")
cycle.create_appraisals()

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

ratings = appraisal.self_ratings
# 70% weightage
@@ -270,16 +270,16 @@ class TestAppraisal(FrappeTestCase):
cycle.create_appraisals()

# unsubmitted appraisals
self.assertRaises(frappe.ValidationError, cycle.complete_cycle)
self.assertRaises(xhiveframework.ValidationError, cycle.complete_cycle)

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)
appraisal.submit()

cycle.complete_cycle()
appraisal = frappe.get_doc(
appraisal = xhiveframework.get_doc(
{
"doctype": "Appraisal",
"employee": self.employee1,
@@ -289,7 +289,7 @@ class TestAppraisal(FrappeTestCase):
)

# transaction against a Completed cycle
self.assertRaises(frappe.ValidationError, appraisal.insert)
self.assertRaises(xhiveframework.ValidationError, appraisal.insert)

def test_cycle_summary(self):
employee2 = make_employee("employee2@example.com", company=self.company, designation="Engineer")
@@ -297,10 +297,10 @@ class TestAppraisal(FrappeTestCase):
cycle = create_appraisal_cycle(designation="Engineer")
cycle.create_appraisals()

appraisal = frappe.db.exists(
appraisal = xhiveframework.db.exists(
"Appraisal", {"appraisal_cycle": cycle.name, "employee": self.employee1}
)
appraisal = frappe.get_doc("Appraisal", appraisal)
appraisal = xhiveframework.get_doc("Appraisal", appraisal)

goal = create_goal(self.employee1, "Quality", appraisal_cycle=cycle.name)
feedback = create_performance_feedback(


+ 7
- 7
hrms/hr/doctype/appraisal_cycle/appraisal_cycle.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2022, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on("Appraisal Cycle", {
xhiveframework.ui.form.on("Appraisal Cycle", {
refresh(frm) {
frm.set_query("department", () => {
return {
@@ -19,11 +19,11 @@ frappe.ui.form.on("Appraisal Cycle", {
if (frm.doc.__islocal) return;

frm.add_custom_button(__("View Goals"), () => {
frappe.route_options = {
xhiveframework.route_options = {
company: frm.doc.company,
appraisal_cycle: frm.doc.name,
};
frappe.set_route("Tree", "Goal");
xhiveframework.set_route("Tree", "Goal");
});

let className = "";
@@ -57,7 +57,7 @@ frappe.ui.form.on("Appraisal Cycle", {
},

get_employees(frm) {
frappe.call({
xhiveframework.call({
method: "set_employees",
doc: frm.doc,
freeze: true,
@@ -86,7 +86,7 @@ frappe.ui.form.on("Appraisal Cycle", {
msg += "<br>";
msg += __("Are you sure you want to proceed?");

frappe.confirm(
xhiveframework.confirm(
msg,
() => {
frm.call({
@@ -105,7 +105,7 @@ frappe.ui.form.on("Appraisal Cycle", {
show_appraisal_summary(frm) {
if (frm.doc.__islocal) return;

frappe.call(
xhiveframework.call(
"hrms.hr.doctype.appraisal_cycle.appraisal_cycle.get_appraisal_cycle_summary",
{cycle_name: frm.doc.name}
).then(r => {


+ 43
- 43
hrms/hr/doctype/appraisal_cycle/appraisal_cycle.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2022, Xhive LLC
# For license information, please see license.txt

import frappe
from frappe import _
from frappe.model.document import Document
from frappe.query_builder.functions import Count
from frappe.query_builder.terms import SubQuery
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.query_builder.functions import Count
from xhiveframework.query_builder.terms import SubQuery


class AppraisalCycle(Document):
@@ -21,7 +21,7 @@ class AppraisalCycle(Document):
return

if self.has_value_changed("kra_evaluation_method") and self.check_if_appraisals_exist():
frappe.throw(
xhiveframework.throw(
_(
"Evaluation Method cannot be changed as there are existing appraisals created for this cycle"
),
@@ -29,12 +29,12 @@ class AppraisalCycle(Document):
)

def check_if_appraisals_exist(self):
return frappe.db.exists(
return xhiveframework.db.exists(
"Appraisal",
{"appraisal_cycle": self.name, "docstatus": ["!=", 2]},
)

@frappe.whitelist()
@xhiveframework.whitelist()
def set_employees(self):
"""Pull employees in appraisee list based on selected filters"""
employees = self.get_employees_for_appraisal()
@@ -64,7 +64,7 @@ class AppraisalCycle(Document):
self.show_missing_template_message()
else:
self.set("appraisees", [])
frappe.msgprint(_("No employees found for the selected criteria"))
xhiveframework.msgprint(_("No employees found for the selected criteria"))

return self

@@ -80,7 +80,7 @@ class AppraisalCycle(Document):
if self.designation:
filters["designation"] = self.designation

employees = frappe.db.get_all(
employees = xhiveframework.db.get_all(
"Employee",
filters=filters,
fields=[
@@ -95,19 +95,19 @@ class AppraisalCycle(Document):
return employees

def get_appraisal_template_map(self):
designations = frappe.get_all("Designation", fields=["name", "appraisal_template"])
appraisal_templates = frappe._dict()
designations = xhiveframework.get_all("Designation", fields=["name", "appraisal_template"])
appraisal_templates = xhiveframework._dict()

for entry in designations:
appraisal_templates[entry.name] = entry.appraisal_template

return appraisal_templates

@frappe.whitelist()
@xhiveframework.whitelist()
def create_appraisals(self):
self.check_permission("write")
if not self.appraisees:
frappe.throw(
xhiveframework.throw(
_("Please select employees to create appraisals for"), title=_("No Employees Selected")
)

@@ -115,13 +115,13 @@ class AppraisalCycle(Document):
self.show_missing_template_message(raise_exception=True)

if len(self.appraisees) > 30:
frappe.enqueue(
xhiveframework.enqueue(
create_appraisals_for_cycle,
queue="long",
timeout=600,
appraisal_cycle=self,
)
frappe.msgprint(
xhiveframework.msgprint(
_("Appraisal creation is queued. It may take a few minutes."),
alert=True,
indicator="blue",
@@ -136,26 +136,26 @@ class AppraisalCycle(Document):
msg += "<br><br>"
msg += _(
"Please set the Appraisal Template for all the {0} or select the template in the Employees table below."
).format(f"""<a href='{frappe.utils.get_url_to_list("Designation")}'>Designations</a>""")
).format(f"""<a href='{xhiveframework.utils.get_url_to_list("Designation")}'>Designations</a>""")

frappe.msgprint(
xhiveframework.msgprint(
msg, title=_("Appraisal Template Missing"), indicator="yellow", raise_exception=raise_exception
)

@frappe.whitelist()
@xhiveframework.whitelist()
def complete_cycle(self):
self.check_permission("write")

draft_appraisals = frappe.db.count("Appraisal", {"appraisal_cycle": self.name, "docstatus": 0})
draft_appraisals = xhiveframework.db.count("Appraisal", {"appraisal_cycle": self.name, "docstatus": 0})

if draft_appraisals:
link = frappe.utils.get_url_to_list("Appraisal") + f"?status=Draft&appraisal_cycle={self.name}"
link = xhiveframework.utils.get_url_to_list("Appraisal") + f"?status=Draft&appraisal_cycle={self.name}"
link = f"""<a href="{link}">documents</a>"""

msg = _("{0} Appraisal(s) are not submitted yet").format(frappe.bold(draft_appraisals))
msg = _("{0} Appraisal(s) are not submitted yet").format(xhiveframework.bold(draft_appraisals))
msg += "<br><br>"
msg += _("Please submit the {0} before marking the cycle as Completed").format(link)
frappe.throw(msg, title=_("Unsubmitted Appraisals"))
xhiveframework.throw(msg, title=_("Unsubmitted Appraisals"))

self.status = "Completed"
self.save()
@@ -170,7 +170,7 @@ def create_appraisals_for_cycle(appraisal_cycle: AppraisalCycle, publish_progres

for employee in appraisal_cycle.appraisees:
try:
appraisal = frappe.get_doc(
appraisal = xhiveframework.get_doc(
{
"doctype": "Appraisal",
"appraisal_template": employee.appraisal_template,
@@ -187,33 +187,33 @@ def create_appraisals_for_cycle(appraisal_cycle: AppraisalCycle, publish_progres

if publish_progress:
count += 1
frappe.publish_progress(
xhiveframework.publish_progress(
count * 100 / len(appraisal_cycle.appraisees), title=_("Creating Appraisals") + "..."
)
except frappe.DuplicateEntryError:
except xhiveframework.DuplicateEntryError:
# already exists
pass


def validate_active_appraisal_cycle(appraisal_cycle: str) -> None:
if frappe.db.get_value("Appraisal Cycle", appraisal_cycle, "status") == "Completed":
if xhiveframework.db.get_value("Appraisal Cycle", appraisal_cycle, "status") == "Completed":
msg = _("Cannot create or change transactions against a {0} Appraisal Cycle.").format(
frappe.bold("Completed")
xhiveframework.bold("Completed")
)
msg += "<br><br>"
msg += _("Mark the cycle as {0} if required.").format(frappe.bold("In Progress"))
msg += _("Mark the cycle as {0} if required.").format(xhiveframework.bold("In Progress"))

frappe.throw(msg, title=_("Not Allowed"))
xhiveframework.throw(msg, title=_("Not Allowed"))


@frappe.whitelist()
@xhiveframework.whitelist()
def get_appraisal_cycle_summary(cycle_name: str) -> dict:
summary = frappe._dict()
summary = xhiveframework._dict()

summary["appraisees"] = frappe.db.count(
summary["appraisees"] = xhiveframework.db.count(
"Appraisal", {"appraisal_cycle": cycle_name, "docstatus": ("!=", 2)}
)
summary["self_appraisal_pending"] = frappe.db.count(
summary["self_appraisal_pending"] = xhiveframework.db.count(
"Appraisal", {"appraisal_cycle": cycle_name, "docstatus": 0, "self_score": 0}
)
summary["goals_missing"] = get_employees_without_goals(cycle_name)
@@ -223,19 +223,19 @@ def get_appraisal_cycle_summary(cycle_name: str) -> dict:


def get_employees_without_goals(cycle_name: str) -> int:
Goal = frappe.qb.DocType("Goal")
Appraisal = frappe.qb.DocType("Appraisal")
Goal = xhiveframework.qb.DocType("Goal")
Appraisal = xhiveframework.qb.DocType("Appraisal")
count = Count("*").as_("count")

filtered_records = SubQuery(
frappe.qb.from_(Goal)
xhiveframework.qb.from_(Goal)
.select(Goal.employee)
.distinct()
.where((Goal.appraisal_cycle == cycle_name) & (Goal.status != "Archived"))
)

goals_missing = (
frappe.qb.from_(Appraisal)
xhiveframework.qb.from_(Appraisal)
.select(count)
.where(
(Appraisal.appraisal_cycle == cycle_name)
@@ -248,19 +248,19 @@ def get_employees_without_goals(cycle_name: str) -> int:


def get_employees_without_feedback(cycle_name: str) -> int:
Feedback = frappe.qb.DocType("Employee Performance Feedback")
Appraisal = frappe.qb.DocType("Appraisal")
Feedback = xhiveframework.qb.DocType("Employee Performance Feedback")
Appraisal = xhiveframework.qb.DocType("Appraisal")
count = Count("*").as_("count")

filtered_records = SubQuery(
frappe.qb.from_(Feedback)
xhiveframework.qb.from_(Feedback)
.select(Feedback.employee)
.distinct()
.where((Feedback.appraisal_cycle == cycle_name) & (Feedback.docstatus == 1))
)

feedback_missing = (
frappe.qb.from_(Appraisal)
xhiveframework.qb.from_(Appraisal)
.select(count)
.where(
(Appraisal.appraisal_cycle == cycle_name)


+ 12
- 12
hrms/hr/doctype/appraisal_cycle/test_appraisal_cycle.py Wyświetl plik

@@ -1,17 +1,17 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2022, Xhive LLC
# See license.txt

import frappe
from frappe.tests.utils import FrappeTestCase
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase

from erpnext.setup.doctype.designation.test_designation import create_designation
from erpnext.setup.doctype.employee.test_employee import make_employee
from xhiveerp.setup.doctype.designation.test_designation import create_designation
from xhiveerp.setup.doctype.employee.test_employee import make_employee

from hrms.hr.doctype.appraisal_template.test_appraisal_template import create_appraisal_template
from hrms.tests.test_utils import create_company


class TestAppraisalCycle(FrappeTestCase):
class TestAppraisalCycle(XhiveframeworkTestCase):
def setUp(self):
company = create_company("_Test Appraisal").name
self.template = create_appraisal_template()
@@ -37,10 +37,10 @@ class TestAppraisalCycle(FrappeTestCase):
cycle = create_appraisal_cycle(designation="Engineer")
cycle.create_appraisals()

appraisals = frappe.db.get_all("Appraisal", filters={"appraisal_cycle": cycle.name})
appraisals = xhiveframework.db.get_all("Appraisal", filters={"appraisal_cycle": cycle.name})
self.assertEqual(len(appraisals), 1)

appraisal = frappe.get_doc("Appraisal", appraisals[0].name)
appraisal = xhiveframework.get_doc("Appraisal", appraisals[0].name)

for i in range(2):
# check if KRAs are set
@@ -55,13 +55,13 @@ class TestAppraisalCycle(FrappeTestCase):


def create_appraisal_cycle(**args):
args = frappe._dict(args)
args = xhiveframework._dict(args)

name = args.name or "Q1"
if frappe.db.exists("Appraisal Cycle", name):
frappe.delete_doc("Appraisal Cycle", name, force=True)
if xhiveframework.db.exists("Appraisal Cycle", name):
xhiveframework.delete_doc("Appraisal Cycle", name, force=True)

appraisal_cycle = frappe.get_doc(
appraisal_cycle = xhiveframework.get_doc(
{
"doctype": "Appraisal Cycle",
"cycle_name": name,


+ 2
- 2
hrms/hr/doctype/appraisal_goal/appraisal_goal.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhive LLC
# License: GNU General Public License v3. See license.txt


from frappe.model.document import Document
from xhiveframework.model.document import Document


class AppraisalGoal(Document):


+ 3
- 3
hrms/hr/doctype/appraisal_kra/appraisal_kra.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2022, Xhive LLC
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class AppraisalKRA(Document):


+ 2
- 2
hrms/hr/doctype/appraisal_template/appraisal_template.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2016, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on("Appraisal Template", {
xhiveframework.ui.form.on("Appraisal Template", {
setup(frm) {
frm.get_field("rating_criteria").grid.editable_fields = [
{fieldname: "criteria", columns: 6},


+ 7
- 7
hrms/hr/doctype/appraisal_template/appraisal_template.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhive LLC
# License: GNU General Public License v3. See license.txt


import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import flt
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.utils import flt


class AppraisalTemplate(Document):
@@ -21,9 +21,9 @@ class AppraisalTemplate(Document):

if flt(total_weightage, 2) != 100.0:
table = _("KRAs") if table_name == "goals" else _("Criteria")
frappe.throw(
xhiveframework.throw(
_("Total weightage for all {0} must add up to 100. Currently, it is {1}%").format(
frappe.bold(table), total_weightage
xhiveframework.bold(table), total_weightage
),
title=_("Incorrect Weightage Allocation"),
)

+ 12
- 12
hrms/hr/doctype/appraisal_template/test_appraisal_template.py Wyświetl plik

@@ -1,18 +1,18 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors
# Copyright (c) 2015, Xhive LLC and Contributors
# See license.txt

import unittest

import frappe
from frappe.tests.utils import FrappeTestCase
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase


class TestAppraisalTemplate(FrappeTestCase):
class TestAppraisalTemplate(XhiveframeworkTestCase):
def test_incorrect_weightage_allocation(self):
template = create_appraisal_template()
template.goals[1].per_weightage = 69.99

self.assertRaises(frappe.ValidationError, template.save)
self.assertRaises(xhiveframework.ValidationError, template.save)

template.reload()
template.goals[1].per_weightage = 70.00
@@ -21,8 +21,8 @@ class TestAppraisalTemplate(FrappeTestCase):

def create_kras(kras):
for entry in kras:
if not frappe.db.exists("KRA", entry):
frappe.get_doc(
if not xhiveframework.db.exists("KRA", entry):
xhiveframework.get_doc(
{
"doctype": "KRA",
"title": entry,
@@ -32,8 +32,8 @@ def create_kras(kras):

def create_criteria(criteria):
for entry in criteria:
if not frappe.db.exists("Employee Feedback Criteria", entry):
frappe.get_doc(
if not xhiveframework.db.exists("Employee Feedback Criteria", entry):
xhiveframework.get_doc(
{
"doctype": "Employee Feedback Criteria",
"criteria": entry,
@@ -44,8 +44,8 @@ def create_criteria(criteria):
def create_appraisal_template(title=None, kras=None, rating_criteria=None):
name = title or "Engineering"

if frappe.db.exists("Appraisal Template", name):
return frappe.get_doc("Appraisal Template", name)
if xhiveframework.db.exists("Appraisal Template", name):
return xhiveframework.get_doc("Appraisal Template", name)

if not kras:
kras = [
@@ -74,7 +74,7 @@ def create_appraisal_template(title=None, kras=None, rating_criteria=None):
create_kras([entry["key_result_area"] for entry in kras])
create_criteria([entry["criteria"] for entry in rating_criteria])

appraisal_template = frappe.new_doc("Appraisal Template")
appraisal_template = xhiveframework.new_doc("Appraisal Template")
appraisal_template.template_title = name
appraisal_template.update({"goals": kras})
appraisal_template.update({"rating_criteria": rating_criteria})


+ 2
- 2
hrms/hr/doctype/appraisal_template_goal/appraisal_template_goal.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhive LLC
# License: GNU General Public License v3. See license.txt


from frappe.model.document import Document
from xhiveframework.model.document import Document


class AppraisalTemplateGoal(Document):


+ 3
- 3
hrms/hr/doctype/appraisee/appraisee.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2022, Xhive LLC
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class Appraisee(Document):


+ 3
- 3
hrms/hr/doctype/attendance/attendance.js Wyświetl plik

@@ -1,15 +1,15 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// Copyright (c) 2015, Xhive LLC
// License: GNU General Public License v3. See license.txt

cur_frm.add_fetch('employee', 'company', 'company');
cur_frm.add_fetch('employee', 'employee_name', 'employee_name');

cur_frm.cscript.onload = function(doc, cdt, cdn) {
if(doc.__islocal) cur_frm.set_value("attendance_date", frappe.datetime.get_today());
if(doc.__islocal) cur_frm.set_value("attendance_date", xhiveframework.datetime.get_today());
}

cur_frm.fields_dict.employee.get_query = function(doc,cdt,cdn) {
return{
query: "erpnext.controllers.queries.employee_query"
query: "xhiveerp.controllers.queries.employee_query"
}
}

+ 52
- 52
hrms/hr/doctype/attendance/attendance.py Wyświetl plik

@@ -1,12 +1,12 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhive LLC
# License: GNU General Public License v3. See license.txt


import frappe
from frappe import _
from frappe.model.document import Document
from frappe.query_builder import Criterion
from frappe.utils import (
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.query_builder import Criterion
from xhiveframework.utils import (
add_days,
cint,
cstr,
@@ -21,17 +21,17 @@ from hrms.hr.doctype.shift_assignment.shift_assignment import has_overlapping_ti
from hrms.hr.utils import get_holiday_dates_for_employee, validate_active_employee


class DuplicateAttendanceError(frappe.ValidationError):
class DuplicateAttendanceError(xhiveframework.ValidationError):
pass


class OverlappingShiftAttendanceError(frappe.ValidationError):
class OverlappingShiftAttendanceError(xhiveframework.ValidationError):
pass


class Attendance(Document):
def validate(self):
from erpnext.controllers.status_updater import validate_status
from xhiveerp.controllers.status_updater import validate_status

validate_status(self.status, ["Present", "Absent", "On Leave", "Half Day", "Work From Home"])
validate_active_employee(self.employee)
@@ -45,7 +45,7 @@ class Attendance(Document):
self.unlink_attendance_from_checkins()

def validate_attendance_date(self):
date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining")
date_of_joining = xhiveframework.db.get_value("Employee", self.employee, "date_of_joining")

# leaves can be marked for future dates
if (
@@ -53,17 +53,17 @@ class Attendance(Document):
and not self.leave_application
and getdate(self.attendance_date) > getdate(nowdate())
):
frappe.throw(
xhiveframework.throw(
_("Attendance can not be marked for future dates: {0}").format(
frappe.bold(format_date(self.attendance_date)),
xhiveframework.bold(format_date(self.attendance_date)),
)
)
elif date_of_joining and getdate(self.attendance_date) < getdate(date_of_joining):
frappe.throw(
xhiveframework.throw(
_("Attendance date {0} can not be less than employee {1}'s joining date: {2}").format(
frappe.bold(format_date(self.attendance_date)),
frappe.bold(self.employee),
frappe.bold(format_date(date_of_joining)),
xhiveframework.bold(format_date(self.attendance_date)),
xhiveframework.bold(self.employee),
xhiveframework.bold(format_date(date_of_joining)),
)
)

@@ -73,10 +73,10 @@ class Attendance(Document):
)

if duplicate:
frappe.throw(
xhiveframework.throw(
_("Attendance for employee {0} is already marked for the date {1}: {2}").format(
frappe.bold(self.employee),
frappe.bold(format_date(self.attendance_date)),
xhiveframework.bold(self.employee),
xhiveframework.bold(format_date(self.attendance_date)),
get_link_to_form("Attendance", duplicate[0].name),
),
title=_("Duplicate Attendance"),
@@ -89,10 +89,10 @@ class Attendance(Document):
)

if attendance:
frappe.throw(
xhiveframework.throw(
_("Attendance for employee {0} is already marked for an overlapping shift {1}: {2}").format(
frappe.bold(self.employee),
frappe.bold(attendance.shift),
xhiveframework.bold(self.employee),
xhiveframework.bold(attendance.shift),
get_link_to_form("Attendance", attendance.name),
),
title=_("Overlapping Shift Attendance"),
@@ -100,11 +100,11 @@ class Attendance(Document):
)

def validate_employee_status(self):
if frappe.db.get_value("Employee", self.employee, "status") == "Inactive":
frappe.throw(_("Cannot mark attendance for an Inactive employee {0}").format(self.employee))
if xhiveframework.db.get_value("Employee", self.employee, "status") == "Inactive":
xhiveframework.throw(_("Cannot mark attendance for an Inactive employee {0}").format(self.employee))

def check_leave_record(self):
leave_record = frappe.db.sql(
leave_record = xhiveframework.db.sql(
"""
select leave_type, half_day, half_day_date
from `tabLeave Application`
@@ -121,18 +121,18 @@ class Attendance(Document):
self.leave_type = d.leave_type
if d.half_day_date == getdate(self.attendance_date):
self.status = "Half Day"
frappe.msgprint(
xhiveframework.msgprint(
_("Employee {0} on Half day on {1}").format(self.employee, format_date(self.attendance_date))
)
else:
self.status = "On Leave"
frappe.msgprint(
xhiveframework.msgprint(
_("Employee {0} is on Leave on {1}").format(self.employee, format_date(self.attendance_date))
)

if self.status in ("On Leave", "Half Day"):
if not leave_record:
frappe.msgprint(
xhiveframework.msgprint(
_("No leave record found for employee {0} on {1}").format(
self.employee, format_date(self.attendance_date)
),
@@ -143,16 +143,16 @@ class Attendance(Document):
self.leave_application = None

def validate_employee(self):
emp = frappe.db.sql(
emp = xhiveframework.db.sql(
"select name from `tabEmployee` where name = %s and status = 'Active'", self.employee
)
if not emp:
frappe.throw(_("Employee {0} is not active or does not exist").format(self.employee))
xhiveframework.throw(_("Employee {0} is not active or does not exist").format(self.employee))

def unlink_attendance_from_checkins(self):
EmployeeCheckin = frappe.qb.DocType("Employee Checkin")
EmployeeCheckin = xhiveframework.qb.DocType("Employee Checkin")
linked_logs = (
frappe.qb.from_(EmployeeCheckin)
xhiveframework.qb.from_(EmployeeCheckin)
.select(EmployeeCheckin.name)
.where(EmployeeCheckin.attendance == self.name)
.for_update()
@@ -161,12 +161,12 @@ class Attendance(Document):

if linked_logs:
(
frappe.qb.update(EmployeeCheckin)
xhiveframework.qb.update(EmployeeCheckin)
.set("attendance", "")
.where(EmployeeCheckin.attendance == self.name)
).run()

frappe.msgprint(
xhiveframework.msgprint(
msg=_("Unlinked Attendance record from Employee Checkins: {}").format(
", ".join(get_link_to_form("Employee Checkin", log.name) for log in linked_logs)
),
@@ -178,9 +178,9 @@ class Attendance(Document):


def get_duplicate_attendance_record(employee, attendance_date, shift, name=None):
attendance = frappe.qb.DocType("Attendance")
attendance = xhiveframework.qb.DocType("Attendance")
query = (
frappe.qb.from_(attendance)
xhiveframework.qb.from_(attendance)
.select(attendance.name)
.where((attendance.employee == employee) & (attendance.docstatus < 2))
)
@@ -218,9 +218,9 @@ def get_overlapping_shift_attendance(employee, attendance_date, shift, name=None
if not shift:
return {}

attendance = frappe.qb.DocType("Attendance")
attendance = xhiveframework.qb.DocType("Attendance")
query = (
frappe.qb.from_(attendance)
xhiveframework.qb.from_(attendance)
.select(attendance.name, attendance.shift)
.where(
(attendance.employee == employee)
@@ -240,16 +240,16 @@ def get_overlapping_shift_attendance(employee, attendance_date, shift, name=None
return {}


@frappe.whitelist()
@xhiveframework.whitelist()
def get_events(start, end, filters=None):
events = []

employee = frappe.db.get_value("Employee", {"user_id": frappe.session.user})
employee = xhiveframework.db.get_value("Employee", {"user_id": xhiveframework.session.user})

if not employee:
return events

from frappe.desk.reportview import get_filters_cond
from xhiveframework.desk.reportview import get_filters_cond

conditions = get_filters_cond("Attendance", filters, [])
add_attendance(events, start, end, conditions=conditions)
@@ -264,7 +264,7 @@ def add_attendance(events, start, end, conditions=None):
if conditions:
query += conditions

for d in frappe.db.sql(query, {"from_date": start, "to_date": end}, as_dict=True):
for d in xhiveframework.db.sql(query, {"from_date": start, "to_date": end}, as_dict=True):
e = {
"name": d.name,
"doctype": "Attendance",
@@ -293,8 +293,8 @@ def mark_attendance(
if get_overlapping_shift_attendance(employee, attendance_date, shift):
return

company = frappe.db.get_value("Employee", employee, "company")
attendance = frappe.get_doc(
company = xhiveframework.db.get_value("Employee", employee, "company")
attendance = xhiveframework.get_doc(
{
"doctype": "Attendance",
"employee": employee,
@@ -313,16 +313,16 @@ def mark_attendance(
return attendance.name


@frappe.whitelist()
@xhiveframework.whitelist()
def mark_bulk_attendance(data):
import json

if isinstance(data, str):
data = json.loads(data)
data = frappe._dict(data)
company = frappe.get_value("Employee", data.employee, "company")
data = xhiveframework._dict(data)
company = xhiveframework.get_value("Employee", data.employee, "company")
if not data.unmarked_days:
frappe.throw(_("Please select a date."))
xhiveframework.throw(_("Please select a date."))
return

for date in data.unmarked_days:
@@ -333,20 +333,20 @@ def mark_bulk_attendance(data):
"status": data.status,
"company": company,
}
attendance = frappe.get_doc(doc_dict).insert()
attendance = xhiveframework.get_doc(doc_dict).insert()
attendance.submit()


@frappe.whitelist()
@xhiveframework.whitelist()
def get_unmarked_days(employee, from_date, to_date, exclude_holidays=0):
joining_date, relieving_date = frappe.get_cached_value(
joining_date, relieving_date = xhiveframework.get_cached_value(
"Employee", employee, ["date_of_joining", "relieving_date"]
)

from_date = max(getdate(from_date), joining_date or getdate(from_date))
to_date = min(getdate(to_date), relieving_date or getdate(to_date))

records = frappe.get_all(
records = xhiveframework.get_all(
"Attendance",
fields=["attendance_date", "employee"],
filters=[


+ 2
- 2
hrms/hr/doctype/attendance/attendance_calendar.js Wyświetl plik

@@ -1,6 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2018, Xhive LLC
// For license information, please see license.txt
frappe.views.calendar["Attendance"] = {
xhiveframework.views.calendar["Attendance"] = {
options: {
header: {
left: 'prev,next today',


+ 8
- 8
hrms/hr/doctype/attendance/attendance_list.js Wyświetl plik

@@ -1,4 +1,4 @@
frappe.listview_settings["Attendance"] = {
xhiveframework.listview_settings["Attendance"] = {
add_fields: ["status", "attendance_date"],

get_indicator: function (doc) {
@@ -21,7 +21,7 @@ frappe.listview_settings["Attendance"] = {
first_day_of_month = first_day_of_month.subtract(1, "month");
}

let dialog = new frappe.ui.Dialog({
let dialog = new xhiveframework.ui.Dialog({
title: __("Mark Attendance"),
fields: [
{
@@ -31,7 +31,7 @@ frappe.listview_settings["Attendance"] = {
options: "Employee",
get_query: () => {
return {
query: "erpnext.controllers.queries.employee_query",
query: "xhiveerp.controllers.queries.employee_query",
};
},
reqd: 1,
@@ -90,27 +90,27 @@ frappe.listview_settings["Attendance"] = {
],
primary_action(data) {
if (cur_dialog.no_unmarked_days_left) {
frappe.msgprint(
xhiveframework.msgprint(
__(
"Attendance from {0} to {1} has already been marked for the Employee {2}",
[data.from_date, data.to_date, data.employee]
)
);
} else {
frappe.confirm(
xhiveframework.confirm(
__("Mark attendance as {0} for {1} on selected dates?", [
data.status,
data.employee,
]),
() => {
frappe.call({
xhiveframework.call({
method: "hrms.hr.doctype.attendance.attendance.mark_bulk_attendance",
args: {
data: data,
},
callback: function (r) {
if (r.message === 1) {
frappe.show_alert({
xhiveframework.show_alert({
message: __("Attendance Marked"),
indicator: "blue",
});
@@ -159,7 +159,7 @@ frappe.listview_settings["Attendance"] = {
dialog.set_df_property("exclude_holidays", "hidden", 0);
dialog.no_unmarked_days_left = false;

frappe
xhiveframework
.call({
method: "hrms.hr.doctype.attendance.attendance.get_unmarked_days",
async: false,


+ 18
- 18
hrms/hr/doctype/attendance/test_attendance.py Wyświetl plik

@@ -1,9 +1,9 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors
# Copyright (c) 2015, Xhive LLC and Contributors
# See license.txt

import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import (
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase
from xhiveframework.utils import (
add_days,
add_months,
get_first_day,
@@ -14,7 +14,7 @@ from frappe.utils import (
nowdate,
)

from erpnext.setup.doctype.employee.test_employee import make_employee
from xhiveerp.setup.doctype.employee.test_employee import make_employee

from hrms.hr.doctype.attendance.attendance import (
DuplicateAttendanceError,
@@ -24,24 +24,24 @@ from hrms.hr.doctype.attendance.attendance import (
)
from hrms.tests.test_utils import get_first_sunday

test_records = frappe.get_test_records("Attendance")
test_records = xhiveframework.get_test_records("Attendance")


class TestAttendance(FrappeTestCase):
class TestAttendance(XhiveframeworkTestCase):
def setUp(self):
from hrms.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list

from_date = get_year_start(add_months(getdate(), -1))
to_date = get_year_ending(getdate())
self.holiday_list = make_holiday_list(from_date=from_date, to_date=to_date)
frappe.db.delete("Attendance")
xhiveframework.db.delete("Attendance")

def test_duplicate_attendance(self):
employee = make_employee("test_duplicate_attendance@example.com", company="_Test Company")
date = nowdate()

mark_attendance(employee, date, "Present")
attendance = frappe.get_doc(
attendance = xhiveframework.get_doc(
{
"doctype": "Attendance",
"employee": employee,
@@ -63,7 +63,7 @@ class TestAttendance(FrappeTestCase):
mark_attendance(employee, date, "Present", shift=shift_1.name)

# attendance record with shift
attendance = frappe.get_doc(
attendance = xhiveframework.get_doc(
{
"doctype": "Attendance",
"employee": employee,
@@ -77,7 +77,7 @@ class TestAttendance(FrappeTestCase):
self.assertRaises(DuplicateAttendanceError, attendance.insert)

# attendance record without any shift
attendance = frappe.get_doc(
attendance = xhiveframework.get_doc(
{
"doctype": "Attendance",
"employee": employee,
@@ -101,7 +101,7 @@ class TestAttendance(FrappeTestCase):
mark_attendance(employee, date, "Present", shift=shift_1.name)

# attendance record with overlapping shift
attendance = frappe.get_doc(
attendance = xhiveframework.get_doc(
{
"doctype": "Attendance",
"employee": employee,
@@ -125,7 +125,7 @@ class TestAttendance(FrappeTestCase):
shift_2 = setup_shift_type(shift_type="Shift 2", start_time="11:00:00", end_time="12:00:00")

mark_attendance(employee, date, "Present", shift_1.name)
frappe.get_doc(
xhiveframework.get_doc(
{
"doctype": "Attendance",
"employee": employee,
@@ -141,7 +141,7 @@ class TestAttendance(FrappeTestCase):
date = nowdate()

attendance = mark_attendance(employee, date, "Absent")
fetch_attendance = frappe.get_value(
fetch_attendance = xhiveframework.get_value(
"Attendance", {"employee": employee, "attendance_date": date, "status": "Absent"}
)
self.assertEqual(attendance, fetch_attendance)
@@ -155,7 +155,7 @@ class TestAttendance(FrappeTestCase):
employee = make_employee(
"test_unmarked_days@example.com", date_of_joining=add_days(attendance_date, -1)
)
frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
xhiveframework.db.set_value("Employee", employee, "holiday_list", self.holiday_list)

mark_attendance(employee, attendance_date, "Present")

@@ -180,7 +180,7 @@ class TestAttendance(FrappeTestCase):
employee = make_employee(
"test_unmarked_days@example.com", date_of_joining=add_days(attendance_date, -1)
)
frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
xhiveframework.db.set_value("Employee", employee, "holiday_list", self.holiday_list)

mark_attendance(employee, attendance_date, "Present")

@@ -208,7 +208,7 @@ class TestAttendance(FrappeTestCase):
"test_unmarked_days_as_per_doj@example.com", date_of_joining=doj, relieving_date=relieving_date
)

frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
xhiveframework.db.set_value("Employee", employee, "holiday_list", self.holiday_list)

attendance_date = add_days(date, 2)
mark_attendance(employee, attendance_date, "Present")
@@ -226,4 +226,4 @@ class TestAttendance(FrappeTestCase):
self.assertNotIn(add_days(relieving_date, 1), unmarked_days)

def tearDown(self):
frappe.db.rollback()
xhiveframework.db.rollback()

+ 3
- 3
hrms/hr/doctype/attendance_request/attendance_request.js Wyświetl plik

@@ -1,6 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2018, Xhive LLC
// For license information, please see license.txt
frappe.ui.form.on("Attendance Request", {
xhiveframework.ui.form.on("Attendance Request", {
refresh(frm) {
frm.trigger("show_attendance_warnings");
},
@@ -13,7 +13,7 @@ frappe.ui.form.on("Attendance Request", {
if (r.message?.length) {
frm.dashboard.reset();
frm.dashboard.add_section(
frappe.render_template("attendance_warnings", {
xhiveframework.render_template("attendance_warnings", {
warnings: r.message || [],
}),
__("Attendance Warnings")


+ 28
- 28
hrms/hr/doctype/attendance_request/attendance_request.py Wyświetl plik

@@ -1,18 +1,18 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2018, Xhive LLC
# For license information, please see license.txt


import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import add_days, date_diff, format_date, get_link_to_form, getdate
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.utils import add_days, date_diff, format_date, get_link_to_form, getdate

from erpnext.setup.doctype.employee.employee import is_holiday
from xhiveerp.setup.doctype.employee.employee import is_holiday

from hrms.hr.utils import validate_active_employee, validate_dates


class OverlappingAttendanceRequestError(frappe.ValidationError):
class OverlappingAttendanceRequestError(xhiveframework.ValidationError):
pass


@@ -26,15 +26,15 @@ class AttendanceRequest(Document):
def validate_half_day(self):
if self.half_day:
if not getdate(self.from_date) <= getdate(self.half_day_date) <= getdate(self.to_date):
frappe.throw(_("Half day date should be in between from date and to date"))
xhiveframework.throw(_("Half day date should be in between from date and to date"))

def validate_request_overlap(self):
if not self.name:
self.name = "New Attendance Request"

Request = frappe.qb.DocType("Attendance Request")
Request = xhiveframework.qb.DocType("Attendance Request")
overlapping_request = (
frappe.qb.from_(Request)
xhiveframework.qb.from_(Request)
.select(Request.name)
.where(
(Request.employee == self.employee)
@@ -52,11 +52,11 @@ class AttendanceRequest(Document):
msg = _(
"Employee {0} already has an Attendance Request {1} that overlaps with this period"
).format(
frappe.bold(self.employee),
xhiveframework.bold(self.employee),
get_link_to_form("Attendance Request", overlapping_request),
)

frappe.throw(
xhiveframework.throw(
msg, title=_("Overlapping Attendance Request"), exc=OverlappingAttendanceRequestError
)

@@ -64,12 +64,12 @@ class AttendanceRequest(Document):
self.create_attendance_records()

def on_cancel(self):
attendance_list = frappe.get_all(
attendance_list = xhiveframework.get_all(
"Attendance", {"employee": self.employee, "attendance_request": self.name, "docstatus": 1}
)
if attendance_list:
for attendance in attendance_list:
attendance_obj = frappe.get_doc("Attendance", attendance["name"])
attendance_obj = xhiveframework.get_doc("Attendance", attendance["name"])
attendance_obj.cancel()

def create_attendance_records(self):
@@ -85,28 +85,28 @@ class AttendanceRequest(Document):

if attendance_name:
# update existing attendance, change the status
doc = frappe.get_doc("Attendance", attendance_name)
doc = xhiveframework.get_doc("Attendance", attendance_name)
old_status = doc.status

if old_status != status:
doc.db_set({"status": status, "attendance_request": self.name})
text = _("changed the status from {0} to {1} via Attendance Request").format(
frappe.bold(old_status), frappe.bold(status)
xhiveframework.bold(old_status), xhiveframework.bold(status)
)
doc.add_comment(comment_type="Info", text=text)

frappe.msgprint(
xhiveframework.msgprint(
_("Updated status from {0} to {1} for date {2} in the attendance record {3}").format(
frappe.bold(old_status),
frappe.bold(status),
frappe.bold(format_date(date)),
xhiveframework.bold(old_status),
xhiveframework.bold(status),
xhiveframework.bold(format_date(date)),
get_link_to_form("Attendance", doc.name),
),
title=_("Attendance Updated"),
)
else:
# submit a new attendance record
doc = frappe.new_doc("Attendance")
doc = xhiveframework.new_doc("Attendance")
doc.employee = self.employee
doc.attendance_date = date
doc.company = self.company
@@ -118,18 +118,18 @@ class AttendanceRequest(Document):
def should_mark_attendance(self, attendance_date: str) -> bool:
# Check if attendance_date is a holiday
if is_holiday(self.employee, attendance_date):
frappe.msgprint(
xhiveframework.msgprint(
_("Attendance not submitted for {0} as it is a Holiday.").format(
frappe.bold(format_date(attendance_date))
xhiveframework.bold(format_date(attendance_date))
)
)
return False

# Check if employee is on leave
if self.has_leave_record(attendance_date):
frappe.msgprint(
xhiveframework.msgprint(
_("Attendance not submitted for {0} as {1} is on leave.").format(
frappe.bold(format_date(attendance_date)), frappe.bold(self.employee)
xhiveframework.bold(format_date(attendance_date)), xhiveframework.bold(self.employee)
)
)
return False
@@ -137,7 +137,7 @@ class AttendanceRequest(Document):
return True

def has_leave_record(self, attendance_date: str) -> str | None:
return frappe.db.exists(
return xhiveframework.db.exists(
"Leave Application",
{
"employee": self.employee,
@@ -148,7 +148,7 @@ class AttendanceRequest(Document):
)

def get_attendance_record(self, attendance_date: str) -> str | None:
return frappe.db.exists(
return xhiveframework.db.exists(
"Attendance",
{
"employee": self.employee,
@@ -165,7 +165,7 @@ class AttendanceRequest(Document):
else:
return "Present"

@frappe.whitelist()
@xhiveframework.whitelist()
def get_attendance_warnings(self) -> list:
attendance_warnings = []
request_days = date_diff(self.to_date, self.from_date) + 1


+ 1
- 1
hrms/hr/doctype/attendance_request/attendance_warnings.html Wyświetl plik

@@ -14,7 +14,7 @@
<tbody>
{% for(var i=0; i < warnings.length; i++) { %}
<tr>
<td class="small">{{ frappe.datetime.str_to_user(warnings[i].date) }}</td>
<td class="small">{{ xhiveframework.datetime.str_to_user(warnings[i].date) }}</td>
<td class="small"> {{ __(warnings[i].action) }} </td>
<td class="small"> {{ __(warnings[i].reason) }} </td>
<td class="small"> {{ warnings[i].record }} </td>


+ 16
- 16
hrms/hr/doctype/attendance_request/test_attendance_request.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2018, Xhive LLC
# See license.txt

import unittest

import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, add_months, get_year_ending, get_year_start, getdate
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase
from xhiveframework.utils import add_days, add_months, get_year_ending, get_year_start, getdate

from hrms.hr.doctype.attendance.attendance import mark_attendance
from hrms.hr.doctype.attendance_request.attendance_request import OverlappingAttendanceRequestError
@@ -19,10 +19,10 @@ from hrms.tests.test_utils import get_first_sunday
test_dependencies = ["Employee"]


class TestAttendanceRequest(FrappeTestCase):
class TestAttendanceRequest(XhiveframeworkTestCase):
def setUp(self):
for doctype in ["Attendance Request", "Attendance"]:
frappe.db.delete(doctype)
xhiveframework.db.delete(doctype)

self.from_date = get_year_start(add_months(getdate(), -1))
self.to_date = get_year_ending(getdate())
@@ -31,7 +31,7 @@ class TestAttendanceRequest(FrappeTestCase):
)

self.employee = get_employee()
frappe.db.set_value("Employee", self.employee.name, "holiday_list", self.holiday_list)
xhiveframework.db.set_value("Employee", self.employee.name, "holiday_list", self.holiday_list)

def test_attendance_request_overlap(self):
create_attendance_request(employee=self.employee.name, reason="On Duty", company="_Test Company")
@@ -43,7 +43,7 @@ class TestAttendanceRequest(FrappeTestCase):
(today, add_days(today, 1)),
(add_days(today, -2), add_days(today, 2)),
]
attendance_request = frappe.get_doc(
attendance_request = xhiveframework.get_doc(
{
"doctype": "Attendance Request",
"employee": self.employee.name,
@@ -101,7 +101,7 @@ class TestAttendanceRequest(FrappeTestCase):
attendance_request = create_attendance_request(
employee=self.employee.name, reason="Work From Home", company="_Test Company"
)
prev_attendance = frappe.get_doc("Attendance", attendance_name)
prev_attendance = xhiveframework.get_doc("Attendance", attendance_name)

# attendance request should overwrite attendance status from Absent to Work From Home
self.assertEqual(prev_attendance.status, "Work From Home")
@@ -109,7 +109,7 @@ class TestAttendanceRequest(FrappeTestCase):

def test_skip_attendance_on_holiday(self):
today = getdate()
holiday_list = frappe.get_doc("Holiday List", self.holiday_list)
holiday_list = xhiveframework.get_doc("Holiday List", self.holiday_list)
holiday_list.append(
"holidays",
{
@@ -130,8 +130,8 @@ class TestAttendanceRequest(FrappeTestCase):
self.assertEqual(records[0].status, "Present")

def test_skip_attendance_on_leave(self):
frappe.delete_doc_if_exists("Leave Type", "Test Skip Attendance", force=1)
leave_type = frappe.get_doc(
xhiveframework.delete_doc_if_exists("Leave Type", "Test Skip Attendance", force=1)
leave_type = xhiveframework.get_doc(
dict(leave_type_name="Test Skip Attendance", doctype="Leave Type")
).insert()

@@ -153,7 +153,7 @@ class TestAttendanceRequest(FrappeTestCase):
self.assertEqual(records[0].status, "Present")

def get_attendance_records(self, attendance_request: str) -> list[dict]:
return frappe.db.get_all(
return xhiveframework.db.get_all(
"Attendance",
{
"attendance_request": attendance_request,
@@ -163,14 +163,14 @@ class TestAttendanceRequest(FrappeTestCase):


def get_employee():
return frappe.get_doc("Employee", "_T-Employee-00001")
return xhiveframework.get_doc("Employee", "_T-Employee-00001")


def create_attendance_request(**args: dict) -> dict:
args = frappe._dict(args)
args = xhiveframework._dict(args)
today = getdate()

attendance_request = frappe.get_doc(
attendance_request = xhiveframework.get_doc(
{
"doctype": "Attendance Request",
"employee": args.employee or get_employee().name,


+ 2
- 2
hrms/hr/doctype/compensatory_leave_request/compensatory_leave_request.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2018, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Compensatory Leave Request', {
xhiveframework.ui.form.on('Compensatory Leave Request', {
refresh: function(frm) {
frm.set_query("leave_type", function() {
return {


+ 20
- 20
hrms/hr/doctype/compensatory_leave_request/compensatory_leave_request.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2018, Xhive LLC
# For license information, please see license.txt


import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import add_days, cint, date_diff, format_date, getdate
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.utils import add_days, cint, date_diff, format_date, getdate

from hrms.hr.utils import (
create_additional_leave_ledger_entry,
@@ -23,19 +23,19 @@ class CompensatoryLeaveRequest(Document):
validate_dates(self, self.work_from_date, self.work_end_date)
if self.half_day:
if not self.half_day_date:
frappe.throw(_("Half Day Date is mandatory"))
xhiveframework.throw(_("Half Day Date is mandatory"))
if (
not getdate(self.work_from_date) <= getdate(self.half_day_date) <= getdate(self.work_end_date)
):
frappe.throw(_("Half Day Date should be in between Work From Date and Work End Date"))
xhiveframework.throw(_("Half Day Date should be in between Work From Date and Work End Date"))
validate_overlap(self, self.work_from_date, self.work_end_date)
self.validate_holidays()
self.validate_attendance()
if not self.leave_type:
frappe.throw(_("Leave Type is madatory"))
xhiveframework.throw(_("Leave Type is madatory"))

def validate_attendance(self):
attendance = frappe.get_all(
attendance = xhiveframework.get_all(
"Attendance",
filters={
"attendance_date": ["between", (self.work_from_date, self.work_end_date)],
@@ -47,22 +47,22 @@ class CompensatoryLeaveRequest(Document):
)

if len(attendance) < date_diff(self.work_end_date, self.work_from_date) + 1:
frappe.throw(_("You are not present all day(s) between compensatory leave request days"))
xhiveframework.throw(_("You are not present all day(s) between compensatory leave request days"))

def validate_holidays(self):
holidays = get_holiday_dates_for_employee(self.employee, self.work_from_date, self.work_end_date)
if len(holidays) < date_diff(self.work_end_date, self.work_from_date) + 1:
if date_diff(self.work_end_date, self.work_from_date):
msg = _("The days between {0} to {1} are not valid holidays.").format(
frappe.bold(format_date(self.work_from_date)), frappe.bold(format_date(self.work_end_date))
xhiveframework.bold(format_date(self.work_from_date)), xhiveframework.bold(format_date(self.work_end_date))
)
else:
msg = _("{0} is not a holiday.").format(frappe.bold(format_date(self.work_from_date)))
msg = _("{0} is not a holiday.").format(xhiveframework.bold(format_date(self.work_from_date)))

frappe.throw(msg)
xhiveframework.throw(msg)

def on_submit(self):
company = frappe.db.get_value("Employee", self.employee, "company")
company = xhiveframework.db.get_value("Employee", self.employee, "company")
date_difference = date_diff(self.work_end_date, self.work_from_date) + 1
if self.half_day:
date_difference -= 0.5
@@ -84,7 +84,7 @@ class CompensatoryLeaveRequest(Document):
leave_allocation = self.create_leave_allocation(leave_period, date_difference)
self.db_set("leave_allocation", leave_allocation.name)
else:
frappe.throw(
xhiveframework.throw(
_("There is no leave period in between {0} and {1}").format(
format_date(self.work_from_date), format_date(self.work_end_date)
)
@@ -95,7 +95,7 @@ class CompensatoryLeaveRequest(Document):
date_difference = date_diff(self.work_end_date, self.work_from_date) + 1
if self.half_day:
date_difference -= 0.5
leave_allocation = frappe.get_doc("Leave Allocation", self.leave_allocation)
leave_allocation = xhiveframework.get_doc("Leave Allocation", self.leave_allocation)
if leave_allocation:
leave_allocation.new_leaves_allocated -= date_difference
if leave_allocation.new_leaves_allocated - date_difference <= 0:
@@ -110,7 +110,7 @@ class CompensatoryLeaveRequest(Document):
)

def get_existing_allocation_for_period(self, leave_period):
leave_allocation = frappe.db.sql(
leave_allocation = xhiveframework.db.sql(
"""
select name
from `tabLeave Allocation`
@@ -130,13 +130,13 @@ class CompensatoryLeaveRequest(Document):
)

if leave_allocation:
return frappe.get_doc("Leave Allocation", leave_allocation[0].name)
return xhiveframework.get_doc("Leave Allocation", leave_allocation[0].name)
else:
return False

def create_leave_allocation(self, leave_period, date_difference):
is_carry_forward = frappe.db.get_value("Leave Type", self.leave_type, "is_carry_forward")
allocation = frappe.get_doc(
is_carry_forward = xhiveframework.db.get_value("Leave Type", self.leave_type, "is_carry_forward")
allocation = xhiveframework.get_doc(
dict(
doctype="Leave Allocation",
employee=self.employee,


+ 18
- 18
hrms/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py Wyświetl plik

@@ -1,10 +1,10 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2018, Xhive LLC
# See license.txt

import unittest

import frappe
from frappe.utils import add_days, add_months, today
import xhiveframework
from xhiveframework.utils import add_days, add_months, today

from hrms.hr.doctype.attendance_request.test_attendance_request import get_employee
from hrms.hr.doctype.leave_application.leave_application import get_leave_balance_on
@@ -15,10 +15,10 @@ test_dependencies = ["Employee"]

class TestCompensatoryLeaveRequest(unittest.TestCase):
def setUp(self):
frappe.db.sql(""" delete from `tabCompensatory Leave Request`""")
frappe.db.sql(""" delete from `tabLeave Ledger Entry`""")
frappe.db.sql(""" delete from `tabLeave Allocation`""")
frappe.db.sql(
xhiveframework.db.sql(""" delete from `tabCompensatory Leave Request`""")
xhiveframework.db.sql(""" delete from `tabLeave Ledger Entry`""")
xhiveframework.db.sql(""" delete from `tabLeave Allocation`""")
xhiveframework.db.sql(
""" delete from `tabAttendance` where attendance_date in {0} """.format(
(today(), add_days(today(), -1))
)
@@ -55,7 +55,7 @@ class TestCompensatoryLeaveRequest(unittest.TestCase):
compensatory_leave_request.submit()

# leave allocation creation on submit
leaves_allocated = frappe.db.get_value(
leaves_allocated = xhiveframework.db.get_value(
"Leave Allocation",
{"name": compensatory_leave_request.leave_allocation},
["total_leaves_allocated"],
@@ -67,7 +67,7 @@ class TestCompensatoryLeaveRequest(unittest.TestCase):
compensatory_leave_request.submit()

# leave allocation updates on submission of second compensatory leave request
leaves_allocated = frappe.db.get_value(
leaves_allocated = xhiveframework.db.get_value(
"Leave Allocation",
{"name": compensatory_leave_request.leave_allocation},
["total_leaves_allocated"],
@@ -82,7 +82,7 @@ class TestCompensatoryLeaveRequest(unittest.TestCase):
compensatory_leave_request.submit()

filters = dict(transaction_name=compensatory_leave_request.leave_allocation)
leave_ledger_entry = frappe.get_all("Leave Ledger Entry", fields="*", filters=filters)
leave_ledger_entry = xhiveframework.get_all("Leave Ledger Entry", fields="*", filters=filters)

self.assertEqual(len(leave_ledger_entry), 1)
self.assertEqual(leave_ledger_entry[0].employee, compensatory_leave_request.employee)
@@ -91,7 +91,7 @@ class TestCompensatoryLeaveRequest(unittest.TestCase):

# check reverse leave ledger entry on cancellation
compensatory_leave_request.cancel()
leave_ledger_entry = frappe.get_all(
leave_ledger_entry = xhiveframework.get_all(
"Leave Ledger Entry", fields="*", filters=filters, order_by="creation desc"
)

@@ -102,7 +102,7 @@ class TestCompensatoryLeaveRequest(unittest.TestCase):


def get_compensatory_leave_request(employee, leave_date=today()):
prev_comp_leave_req = frappe.db.get_value(
prev_comp_leave_req = xhiveframework.db.get_value(
"Compensatory Leave Request",
dict(
leave_type="Compensatory Off",
@@ -113,9 +113,9 @@ def get_compensatory_leave_request(employee, leave_date=today()):
"name",
)
if prev_comp_leave_req:
return frappe.get_doc("Compensatory Leave Request", prev_comp_leave_req)
return xhiveframework.get_doc("Compensatory Leave Request", prev_comp_leave_req)

return frappe.get_doc(
return xhiveframework.get_doc(
dict(
doctype="Compensatory Leave Request",
employee=employee,
@@ -128,10 +128,10 @@ def get_compensatory_leave_request(employee, leave_date=today()):


def mark_attendance(employee, date=today(), status="Present"):
if not frappe.db.exists(
if not xhiveframework.db.exists(
dict(doctype="Attendance", employee=employee.name, attendance_date=date, status="Present")
):
attendance = frappe.get_doc(
attendance = xhiveframework.get_doc(
{"doctype": "Attendance", "employee": employee.name, "attendance_date": date, "status": status}
)
attendance.save()
@@ -139,10 +139,10 @@ def mark_attendance(employee, date=today(), status="Present"):


def create_holiday_list():
if frappe.db.exists("Holiday List", "_Test Compensatory Leave"):
if xhiveframework.db.exists("Holiday List", "_Test Compensatory Leave"):
return

holiday_list = frappe.get_doc(
holiday_list = xhiveframework.get_doc(
{
"doctype": "Holiday List",
"from_date": add_months(today(), -3),


+ 2
- 2
hrms/hr/doctype/daily_work_summary/daily_work_summary.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2016, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Daily Work Summary', {
xhiveframework.ui.form.on('Daily Work Summary', {
refresh: function (frm) {

}


+ 17
- 17
hrms/hr/doctype/daily_work_summary/daily_work_summary.py Wyświetl plik

@@ -1,25 +1,25 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2015, Xhive LLC
# For license information, please see license.txt


from email_reply_parser import EmailReplyParser

import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import global_date_format
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.utils import global_date_format


class DailyWorkSummary(Document):
def send_mails(self, dws_group, emails):
"""Send emails to get daily work summary to all users \
in selected daily work summary group"""
incoming_email_account = frappe.db.get_value(
incoming_email_account = xhiveframework.db.get_value(
"Email Account", dict(enable_incoming=1, default_incoming=1), "email_id"
)

self.db_set("email_sent_to", "\n".join(emails))
frappe.sendmail(
xhiveframework.sendmail(
recipients=emails,
message=dws_group.message,
subject=dws_group.subject,
@@ -32,7 +32,7 @@ class DailyWorkSummary(Document):
"""Send summary of all replies. Called at midnight"""
args = self.get_message_details()
emails = get_user_emails_from_group(self.daily_work_summary_group)
frappe.sendmail(
xhiveframework.sendmail(
recipients=emails,
template="daily_work_summary",
args=args,
@@ -45,9 +45,9 @@ class DailyWorkSummary(Document):

def get_message_details(self):
"""Return args for template"""
dws_group = frappe.get_doc("Daily Work Summary Group", self.daily_work_summary_group)
dws_group = xhiveframework.get_doc("Daily Work Summary Group", self.daily_work_summary_group)

replies = frappe.get_all(
replies = xhiveframework.get_all(
"Communication",
fields=["content", "text_content", "sender"],
filters=dict(
@@ -62,7 +62,7 @@ class DailyWorkSummary(Document):
did_not_reply = self.email_sent_to.split()

for d in replies:
user = frappe.db.get_values(
user = xhiveframework.db.get_values(
"User", {"email": d.sender}, ["full_name", "user_image"], as_dict=True
)

@@ -73,11 +73,11 @@ class DailyWorkSummary(Document):
# make thumbnail image
try:
if original_image:
file_name = frappe.get_list("File", {"file_url": original_image})
file_name = xhiveframework.get_list("File", {"file_url": original_image})

if file_name:
file_name = file_name[0].name
file_doc = frappe.get_doc("File", file_name)
file_doc = xhiveframework.get_doc("File", file_name)
thumbnail_image = file_doc.make_thumbnail(
set_as_thumbnail=False, width=100, height=100, crop=True
)
@@ -88,10 +88,10 @@ class DailyWorkSummary(Document):
if d.sender in did_not_reply:
did_not_reply.remove(d.sender)
if d.text_content:
d.content = frappe.utils.md_to_html(EmailReplyParser.parse_reply(d.text_content))
d.content = xhiveframework.utils.md_to_html(EmailReplyParser.parse_reply(d.text_content))

did_not_reply = [
(frappe.db.get_value("User", {"email": email}, "full_name") or email) for email in did_not_reply
(xhiveframework.db.get_value("User", {"email": email}, "full_name") or email) for email in did_not_reply
]

return dict(
@@ -109,7 +109,7 @@ def get_user_emails_from_group(group):
:param group: Daily Work Summary Group `name`"""
group_doc = group
if isinstance(group_doc, str):
group_doc = frappe.get_doc("Daily Work Summary Group", group)
group_doc = xhiveframework.get_doc("Daily Work Summary Group", group)

emails = get_users_email(group_doc)

@@ -117,4 +117,4 @@ def get_user_emails_from_group(group):


def get_users_email(doc):
return [d.email for d in doc.users if frappe.db.get_value("User", d.user, "enabled")]
return [d.email for d in doc.users if xhiveframework.db.get_value("User", d.user, "enabled")]

+ 17
- 17
hrms/hr/doctype/daily_work_summary/test_daily_work_summary.py Wyświetl plik

@@ -1,13 +1,13 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2015, Xhive LLC
# See license.txt

import os
import unittest

import frappe
import frappe.utils
import xhiveframework
import xhiveframework.utils

# test_records = frappe.get_test_records('Daily Work Summary')
# test_records = xhiveframework.get_test_records('Daily Work Summary')


class TestDailyWorkSummary(unittest.TestCase):
@@ -22,7 +22,7 @@ class TestDailyWorkSummary(unittest.TestCase):

def test_email_trigger_failed(self):
hour = "00:00"
if frappe.utils.nowtime().split(":")[0] == "00":
if xhiveframework.utils.nowtime().split(":")[0] == "00":
hour = "01:00"

self.setup_and_prepare_test(hour)
@@ -46,12 +46,12 @@ class TestDailyWorkSummary(unittest.TestCase):
]

# pull the mail
email_account = frappe.get_doc("Email Account", "_Test Email Account 1")
email_account = xhiveframework.get_doc("Email Account", "_Test Email Account 1")
email_account.db_set("enable_incoming", 1)
email_account.receive(test_mails=test_mails)

daily_work_summary = frappe.get_doc(
"Daily Work Summary", frappe.get_all("Daily Work Summary")[0].name
daily_work_summary = xhiveframework.get_doc(
"Daily Work Summary", xhiveframework.get_all("Daily Work Summary")[0].name
)

args = daily_work_summary.get_message_details()
@@ -59,13 +59,13 @@ class TestDailyWorkSummary(unittest.TestCase):
self.assertTrue("I built Daily Work Summary!" in args.get("replies")[0].content)

def setup_and_prepare_test(self, hour=None):
frappe.db.sql("delete from `tabDaily Work Summary`")
frappe.db.sql("delete from `tabEmail Queue`")
frappe.db.sql("delete from `tabEmail Queue Recipient`")
frappe.db.sql("delete from `tabCommunication`")
frappe.db.sql("delete from `tabDaily Work Summary Group`")
xhiveframework.db.sql("delete from `tabDaily Work Summary`")
xhiveframework.db.sql("delete from `tabEmail Queue`")
xhiveframework.db.sql("delete from `tabEmail Queue Recipient`")
xhiveframework.db.sql("delete from `tabCommunication`")
xhiveframework.db.sql("delete from `tabDaily Work Summary Group`")

self.users = frappe.get_all(
self.users = xhiveframework.get_all(
"User", fields=["email"], filters=dict(email=("!=", "test@example.com"))
)
self.setup_groups(hour)
@@ -76,7 +76,7 @@ class TestDailyWorkSummary(unittest.TestCase):

# check if emails are created

self.emails = frappe.db.sql(
self.emails = xhiveframework.db.sql(
"""select r.recipient, q.message, q.message_id \
from `tabEmail Queue` as q, `tabEmail Queue Recipient` as r \
where q.name = r.parent""",
@@ -86,10 +86,10 @@ class TestDailyWorkSummary(unittest.TestCase):
def setup_groups(self, hour=None):
# setup email to trigger at this hour
if not hour:
hour = frappe.utils.nowtime().split(":")[0]
hour = xhiveframework.utils.nowtime().split(":")[0]
hour = hour + ":00"

groups = frappe.get_doc(
groups = xhiveframework.get_doc(
dict(
doctype="Daily Work Summary Group",
name="Daily Work Summary",


+ 7
- 7
hrms/hr/doctype/daily_work_summary/test_data/test-reply.raw Wyświetl plik

@@ -19,17 +19,17 @@ Content-Type: text/plain;

I built Daily Work Summary!

> On 10-Nov-2016, at 3:20 PM, Frappe <test@erpnext.com> wrote:
> On 10-Nov-2016, at 3:20 PM, Xhiveframework <test@xhiveerp.com> wrote:
>=20
> Please share what did you do today. If you reply by midnight, your =
response will be recorded!
>=20
> This email was sent to rmehta@gmail.com
> Unsubscribe from this list =
<http://demo-test.erpnext.com.dev/api/method/frappe.email.queue.unsubscrib=
<http://demo-test.xhiveerp.com.dev/api/method/xhiveframework.email.queue.unsubscrib=
e?email=3Drmehta%40gmail.com&name=3D26cc3e5a5d&doctype=3DDaily+Work+Summar=
y&_signature=3D2c7ab37e6d775e5a481e9b4376154a41>
> Sent via ERPNext <https://erpnext.com/?source=3Dvia_email_footer>
> Sent via XhiveERP <https://xhiveerp.com/?source=3Dvia_email_footer>


--Apple-Mail=_29597CF7-20DD-4184-B3FA-85582C5C4361
@@ -37,7 +37,7 @@ Content-Transfer-Encoding: 7bit
Content-Type: text/html;
charset=us-ascii

<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I built Daily Work Summary!<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 10-Nov-2016, at 3:20 PM, Frappe &lt;<a href="mailto:test@erpnext.com" class="">test@erpnext.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">
<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I built Daily Work Summary!<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 10-Nov-2016, at 3:20 PM, Xhiveframework &lt;<a href="mailto:test@xhiveerp.com" class="">test@xhiveerp.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">


<meta name="viewport" content="width=device-width" class="">
@@ -57,13 +57,13 @@ Content-Type: text/html;
<div style="margin: 15px auto; padding: 0px 7px; text-align: center; color: #8d99a6;" class="">
This email was sent to <a href="mailto:rmehta@gmail.com" class="">rmehta@gmail.com</a>
<p style="margin: 15px auto;" class="">
<a href="http://demo-test.erpnext.com.dev/api/method/frappe.email.queue.unsubscribe?email=rmehta%40gmail.com&amp;name=26cc3e5a5d&amp;doctype=Daily+Work+Summary&amp;_signature=2c7ab37e6d775e5a481e9b4376154a41" style="color: #8d99a6; text-decoration: underline;
<a href="http://demo-test.xhiveerp.com.dev/api/method/xhiveframework.email.queue.unsubscribe?email=rmehta%40gmail.com&amp;name=26cc3e5a5d&amp;doctype=Daily+Work+Summary&amp;_signature=2c7ab37e6d775e5a481e9b4376154a41" style="color: #8d99a6; text-decoration: underline;
target=" _blank"="" class="">Unsubscribe from this list
</a>
</p>
</div><div style="margin: 15px auto;" class=""><div style="text-align: center;" class="">
<a href="https://erpnext.com/?source=via_email_footer" target="_blank" style="color: #8d99a6;" class="">
Sent via ERPNext
<a href="https://xhiveerp.com/?source=via_email_footer" target="_blank" style="color: #8d99a6;" class="">
Sent via XhiveERP
</a>
</div></div>
</div>


+ 3
- 3
hrms/hr/doctype/daily_work_summary_group/daily_work_summary_group.js Wyświetl plik

@@ -1,11 +1,11 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2018, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Daily Work Summary Group', {
xhiveframework.ui.form.on('Daily Work Summary Group', {
refresh: function (frm) {
if (!frm.is_new()) {
frm.add_custom_button(__('Daily Work Summary'), function () {
frappe.set_route('List', 'Daily Work Summary');
xhiveframework.set_route('List', 'Daily Work Summary');
});
}
}


+ 15
- 15
hrms/hr/doctype/daily_work_summary_group/daily_work_summary_group.py Wyświetl plik

@@ -1,13 +1,13 @@
# # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# # Copyright (c) 2015, Xhive LLC
# # For license information, please see license.txt


import frappe
import frappe.utils
from frappe import _
from frappe.model.document import Document
import xhiveframework
import xhiveframework.utils
from xhiveframework import _
from xhiveframework.model.document import Document

from erpnext.setup.doctype.holiday_list.holiday_list import is_holiday
from xhiveerp.setup.doctype.holiday_list.holiday_list import is_holiday

from hrms.hr.doctype.daily_work_summary.daily_work_summary import get_user_emails_from_group

@@ -15,8 +15,8 @@ from hrms.hr.doctype.daily_work_summary.daily_work_summary import get_user_email
class DailyWorkSummaryGroup(Document):
def validate(self):
if self.users:
if not frappe.flags.in_test and not is_incoming_account_enabled():
frappe.throw(
if not xhiveframework.flags.in_test and not is_incoming_account_enabled():
xhiveframework.throw(
_("Please enable default incoming account before creating Daily Work Summary Group")
)

@@ -24,9 +24,9 @@ class DailyWorkSummaryGroup(Document):
def trigger_emails():
"""Send emails to Employees at the given hour asking
them what did they work on today"""
groups = frappe.get_all("Daily Work Summary Group")
groups = xhiveframework.get_all("Daily Work Summary Group")
for d in groups:
group_doc = frappe.get_doc("Daily Work Summary Group", d)
group_doc = xhiveframework.get_doc("Daily Work Summary Group", d)
if (
is_current_hour(group_doc.send_emails_at)
and not is_holiday(group_doc.holiday_list)
@@ -35,22 +35,22 @@ def trigger_emails():
emails = get_user_emails_from_group(group_doc)
# find emails relating to a company
if emails:
daily_work_summary = frappe.get_doc(
daily_work_summary = xhiveframework.get_doc(
dict(doctype="Daily Work Summary", daily_work_summary_group=group_doc.name)
).insert()
daily_work_summary.send_mails(group_doc, emails)


def is_current_hour(hour):
return frappe.utils.nowtime().split(":")[0] == hour.split(":")[0]
return xhiveframework.utils.nowtime().split(":")[0] == hour.split(":")[0]


def send_summary():
"""Send summary to everyone"""
for d in frappe.get_all("Daily Work Summary", dict(status="Open")):
daily_work_summary = frappe.get_doc("Daily Work Summary", d.name)
for d in xhiveframework.get_all("Daily Work Summary", dict(status="Open")):
daily_work_summary = xhiveframework.get_doc("Daily Work Summary", d.name)
daily_work_summary.send_summary()


def is_incoming_account_enabled():
return frappe.db.get_value("Email Account", dict(enable_incoming=1, default_incoming=1))
return xhiveframework.db.get_value("Email Account", dict(enable_incoming=1, default_incoming=1))

+ 2
- 2
hrms/hr/doctype/daily_work_summary_group_user/daily_work_summary_group_user.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2018, Xhive LLC
# For license information, please see license.txt


from frappe.model.document import Document
from xhiveframework.model.document import Document


class DailyWorkSummaryGroupUser(Document):


+ 17
- 17
hrms/hr/doctype/department_approver/department_approver.py Wyświetl plik

@@ -1,27 +1,27 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2018, Xhive LLC
# For license information, please see license.txt


import frappe
from frappe import _
from frappe.model.document import Document
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document


class DepartmentApprover(Document):
pass


@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
@xhiveframework.whitelist()
@xhiveframework.validate_and_sanitize_search_inputs
def get_approvers(doctype, txt, searchfield, start, page_len, filters):

if not filters.get("employee"):
frappe.throw(_("Please select Employee first."))
xhiveframework.throw(_("Please select Employee first."))

approvers = []
department_details = {}
department_list = []
employee = frappe.get_value(
employee = xhiveframework.get_value(
"Employee",
filters.get("employee"),
["employee_name", "department", "leave_approver", "expense_approver", "shift_request_approver"],
@@ -30,11 +30,11 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):

employee_department = filters.get("department") or employee.department
if employee_department:
department_details = frappe.db.get_value(
department_details = xhiveframework.db.get_value(
"Department", {"name": employee_department}, ["lft", "rgt"], as_dict=True
)
if department_details:
department_list = frappe.db.sql(
department_list = xhiveframework.db.sql(
"""select name from `tabDepartment` where lft <= %s
and rgt >= %s
and disabled=0
@@ -45,17 +45,17 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):

if filters.get("doctype") == "Leave Application" and employee.leave_approver:
approvers.append(
frappe.db.get_value("User", employee.leave_approver, ["name", "first_name", "last_name"])
xhiveframework.db.get_value("User", employee.leave_approver, ["name", "first_name", "last_name"])
)

if filters.get("doctype") == "Expense Claim" and employee.expense_approver:
approvers.append(
frappe.db.get_value("User", employee.expense_approver, ["name", "first_name", "last_name"])
xhiveframework.db.get_value("User", employee.expense_approver, ["name", "first_name", "last_name"])
)

if filters.get("doctype") == "Shift Request" and employee.shift_request_approver:
approvers.append(
frappe.db.get_value(
xhiveframework.db.get_value(
"User", employee.shift_request_approver, ["name", "first_name", "last_name"]
)
)
@@ -71,7 +71,7 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):
field_name = "Shift Request Approver"
if department_list:
for d in department_list:
approvers += frappe.db.sql(
approvers += xhiveframework.db.sql(
"""select user.name, user.first_name, user.last_name from
tabUser user, `tabDepartment Approver` approver where
approver.parent = %s
@@ -84,10 +84,10 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):

if len(approvers) == 0:
error_msg = _("Please set {0} for the Employee: {1}").format(
_(field_name), frappe.bold(employee.employee_name)
_(field_name), xhiveframework.bold(employee.employee_name)
)
if department_list:
error_msg += " " + _("or for Department: {0}").format(frappe.bold(employee_department))
frappe.throw(error_msg, title=_("{0} Missing").format(_(field_name)))
error_msg += " " + _("or for Department: {0}").format(xhiveframework.bold(employee_department))
xhiveframework.throw(error_msg, title=_("{0} Missing").format(_(field_name)))

return set(tuple(approver) for approver in approvers)

+ 3
- 3
hrms/hr/doctype/designation_skill/designation_skill.py Wyświetl plik

@@ -1,9 +1,9 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2019, Xhive LLC
# For license information, please see license.txt


# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class DesignationSkill(Document):


+ 27
- 27
hrms/hr/doctype/employee_advance/employee_advance.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2017, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Employee Advance', {
xhiveframework.ui.form.on('Employee Advance', {
setup: function(frm) {
frm.add_fetch("employee", "company", "company");
frm.add_fetch("company", "default_employee_advance_account", "advance_account");
@@ -16,9 +16,9 @@ frappe.ui.form.on('Employee Advance', {

frm.set_query("advance_account", function() {
if (!frm.doc.employee) {
frappe.msgprint(__("Please select employee first"));
xhiveframework.msgprint(__("Please select employee first"));
}
let company_currency = erpnext.get_currency(frm.doc.company);
let company_currency = xhiveerp.get_currency(frm.doc.company);
let currencies = [company_currency];
if (frm.doc.currency && (frm.doc.currency != company_currency)) {
currencies.push(frm.doc.currency);
@@ -46,7 +46,7 @@ frappe.ui.form.on('Employee Advance', {
refresh: function(frm) {
if (frm.doc.docstatus === 1 &&
(flt(frm.doc.paid_amount) < flt(frm.doc.advance_amount)) &&
frappe.model.can_create("Payment Entry")) {
xhiveframework.model.can_create("Payment Entry")) {
frm.add_custom_button(__('Payment'),
function () {
frm.events.make_payment_entry(frm);
@@ -54,7 +54,7 @@ frappe.ui.form.on('Employee Advance', {
} else if (
frm.doc.docstatus === 1 &&
flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) - flt(frm.doc.return_amount) &&
frappe.model.can_create("Expense Claim")
xhiveframework.model.can_create("Expense Claim")
) {
frm.add_custom_button(
__("Expense Claim"),
@@ -69,11 +69,11 @@ frappe.ui.form.on('Employee Advance', {
frm.doc.docstatus === 1
&& (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) - flt(frm.doc.return_amount))
) {
if (frm.doc.repay_unclaimed_amount_from_salary == 0 && frappe.model.can_create("Journal Entry")) {
if (frm.doc.repay_unclaimed_amount_from_salary == 0 && xhiveframework.model.can_create("Journal Entry")) {
frm.add_custom_button(__("Return"), function() {
frm.trigger('make_return_entry');
}, __('Create'));
} else if (frm.doc.repay_unclaimed_amount_from_salary == 1 && frappe.model.can_create("Additional Salary")) {
} else if (frm.doc.repay_unclaimed_amount_from_salary == 1 && xhiveframework.model.can_create("Additional Salary")) {
frm.add_custom_button(__("Deduction from Salary"), function() {
frm.events.make_deduction_via_additional_salary(frm);
}, __('Create'));
@@ -82,14 +82,14 @@ frappe.ui.form.on('Employee Advance', {
},

make_deduction_via_additional_salary: function(frm) {
frappe.call({
xhiveframework.call({
method: "hrms.hr.doctype.employee_advance.employee_advance.create_return_through_additional_salary",
args: {
doc: frm.doc
},
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
var doclist = xhiveframework.model.sync(r.message);
xhiveframework.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
},
@@ -99,21 +99,21 @@ frappe.ui.form.on('Employee Advance', {
if (frm.doc.__onload && frm.doc.__onload.make_payment_via_journal_entry) {
method = "hrms.hr.doctype.employee_advance.employee_advance.make_bank_entry";
}
return frappe.call({
return xhiveframework.call({
method: method,
args: {
"dt": frm.doc.doctype,
"dn": frm.doc.name
},
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
var doclist = xhiveframework.model.sync(r.message);
xhiveframework.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
},

make_expense_claim: function(frm) {
return frappe.call({
return xhiveframework.call({
method: "hrms.hr.doctype.expense_claim.expense_claim.get_expense_claim",
args: {
"employee_name": frm.doc.employee,
@@ -124,14 +124,14 @@ frappe.ui.form.on('Employee Advance', {
"claimed_amount": frm.doc.claimed_amount
},
callback: function(r) {
const doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
const doclist = xhiveframework.model.sync(r.message);
xhiveframework.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
},

make_return_entry: function(frm) {
frappe.call({
xhiveframework.call({
method: 'hrms.hr.doctype.employee_advance.employee_advance.make_return_entry',
args: {
'employee': frm.doc.employee,
@@ -144,15 +144,15 @@ frappe.ui.form.on('Employee Advance', {
'exchange_rate': frm.doc.exchange_rate
},
callback: function(r) {
const doclist = frappe.model.sync(r.message);
frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
const doclist = xhiveframework.model.sync(r.message);
xhiveframework.set_route('Form', doclist[0].doctype, doclist[0].name);
}
});
},

employee: function(frm) {
if (frm.doc.employee) {
frappe.run_serially([
xhiveframework.run_serially([
() => frm.trigger('get_employee_currency'),
() => frm.trigger('get_pending_amount')
]);
@@ -160,7 +160,7 @@ frappe.ui.form.on('Employee Advance', {
},

get_pending_amount: function(frm) {
frappe.call({
xhiveframework.call({
method: "hrms.hr.doctype.employee_advance.employee_advance.get_pending_amount",
args: {
"employee": frm.doc.employee,
@@ -173,7 +173,7 @@ frappe.ui.form.on('Employee Advance', {
},

get_employee_currency: function(frm) {
frappe.call({
xhiveframework.call({
method: "hrms.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
args: {
employee: frm.doc.employee,
@@ -192,9 +192,9 @@ frappe.ui.form.on('Employee Advance', {
var from_currency = frm.doc.currency;
var company_currency;
if (!frm.doc.company) {
company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
company_currency = xhiveerp.get_currency(xhiveframework.defaults.get_default("Company"));
} else {
company_currency = erpnext.get_currency(frm.doc.company);
company_currency = xhiveerp.get_currency(frm.doc.company);
}
if (from_currency != company_currency) {
frm.events.set_exchange_rate(frm, from_currency, company_currency);
@@ -208,8 +208,8 @@ frappe.ui.form.on('Employee Advance', {
},

set_exchange_rate: function(frm, from_currency, company_currency) {
frappe.call({
method: "erpnext.setup.utils.get_exchange_rate",
xhiveframework.call({
method: "xhiveerp.setup.utils.get_exchange_rate",
args: {
from_currency: from_currency,
to_currency: company_currency,


+ 36
- 36
hrms/hr/doctype/employee_advance/employee_advance.py Wyświetl plik

@@ -1,26 +1,26 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2017, Xhive LLC
# For license information, please see license.txt


import frappe
from frappe import _
from frappe.model.document import Document
from frappe.query_builder.functions import Sum
from frappe.utils import flt, nowdate
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.query_builder.functions import Sum
from xhiveframework.utils import flt, nowdate

import erpnext
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
import xhiveerp
from xhiveerp.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account

from hrms.hr.utils import validate_active_employee


class EmployeeAdvanceOverPayment(frappe.ValidationError):
class EmployeeAdvanceOverPayment(xhiveframework.ValidationError):
pass


class EmployeeAdvance(Document):
def onload(self):
self.get("__onload").make_payment_via_journal_entry = frappe.db.get_single_value(
self.get("__onload").make_payment_via_journal_entry = xhiveframework.db.get_single_value(
"Accounts Settings", "make_payment_via_journal_entry"
)

@@ -69,10 +69,10 @@ class EmployeeAdvance(Document):
self.status = status

def set_total_advance_paid(self):
gle = frappe.qb.DocType("GL Entry")
gle = xhiveframework.qb.DocType("GL Entry")

paid_amount = (
frappe.qb.from_(gle)
xhiveframework.qb.from_(gle)
.select(Sum(gle.debit).as_("paid_amount"))
.where(
(gle.against_voucher_type == "Employee Advance")
@@ -85,7 +85,7 @@ class EmployeeAdvance(Document):
).run(as_dict=True)[0].paid_amount or 0

return_amount = (
frappe.qb.from_(gle)
xhiveframework.qb.from_(gle)
.select(Sum(gle.credit).as_("return_amount"))
.where(
(gle.against_voucher_type == "Employee Advance")
@@ -104,13 +104,13 @@ class EmployeeAdvance(Document):
return_amount = flt(return_amount) / flt(self.exchange_rate)

if flt(paid_amount) > self.advance_amount:
frappe.throw(
xhiveframework.throw(
_("Row {0}# Paid Amount cannot be greater than requested advance amount"),
EmployeeAdvanceOverPayment,
)

if flt(return_amount) > self.paid_amount - self.claimed_amount:
frappe.throw(_("Return amount cannot be greater unclaimed amount"))
xhiveframework.throw(_("Return amount cannot be greater unclaimed amount"))

self.db_set("paid_amount", paid_amount)
self.db_set("return_amount", return_amount)
@@ -118,7 +118,7 @@ class EmployeeAdvance(Document):

def update_claimed_amount(self):
claimed_amount = (
frappe.db.sql(
xhiveframework.db.sql(
"""
SELECT sum(ifnull(allocated_amount, 0))
FROM `tabExpense Claim Advance` eca, `tabExpense Claim` ec
@@ -134,14 +134,14 @@ class EmployeeAdvance(Document):
or 0
)

frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
xhiveframework.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
self.reload()
self.set_status(update=True)


@frappe.whitelist()
@xhiveframework.whitelist()
def get_pending_amount(employee, posting_date):
employee_due_amount = frappe.get_all(
employee_due_amount = xhiveframework.get_all(
"Employee Advance",
filters={"employee": employee, "docstatus": 1, "posting_date": ("<=", posting_date)},
fields=["advance_amount", "paid_amount"],
@@ -149,16 +149,16 @@ def get_pending_amount(employee, posting_date):
return sum([(emp.advance_amount - emp.paid_amount) for emp in employee_due_amount])


@frappe.whitelist()
@xhiveframework.whitelist()
def make_bank_entry(dt, dn):
doc = frappe.get_doc(dt, dn)
doc = xhiveframework.get_doc(dt, dn)
payment_account = get_default_bank_cash_account(
doc.company, account_type="Cash", mode_of_payment=doc.mode_of_payment
)
if not payment_account:
frappe.throw(_("Please set a Default Cash Account in Company defaults"))
xhiveframework.throw(_("Please set a Default Cash Account in Company defaults"))

advance_account_currency = frappe.db.get_value("Account", doc.advance_account, "account_currency")
advance_account_currency = xhiveframework.db.get_value("Account", doc.advance_account, "account_currency")

advance_amount, advance_exchange_rate = get_advance_amount_advance_exchange_rate(
advance_account_currency, doc
@@ -166,7 +166,7 @@ def make_bank_entry(dt, dn):

paying_amount, paying_exchange_rate = get_paying_amount_paying_exchange_rate(payment_account, doc)

je = frappe.new_doc("Journal Entry")
je = xhiveframework.new_doc("Journal Entry")
je.posting_date = nowdate()
je.voucher_type = "Bank Entry"
je.company = doc.company
@@ -183,7 +183,7 @@ def make_bank_entry(dt, dn):
"reference_type": "Employee Advance",
"reference_name": doc.name,
"party_type": "Employee",
"cost_center": erpnext.get_default_cost_center(doc.company),
"cost_center": xhiveerp.get_default_cost_center(doc.company),
"party": doc.employee,
"is_advance": "Yes",
},
@@ -193,7 +193,7 @@ def make_bank_entry(dt, dn):
"accounts",
{
"account": payment_account.account,
"cost_center": erpnext.get_default_cost_center(doc.company),
"cost_center": xhiveerp.get_default_cost_center(doc.company),
"credit_in_account_currency": flt(paying_amount),
"account_currency": payment_account.account_currency,
"account_type": payment_account.account_type,
@@ -226,14 +226,14 @@ def get_paying_amount_paying_exchange_rate(payment_account, doc):
return paying_amount, paying_exchange_rate


@frappe.whitelist()
@xhiveframework.whitelist()
def create_return_through_additional_salary(doc):
import json

if isinstance(doc, str):
doc = frappe._dict(json.loads(doc))
doc = xhiveframework._dict(json.loads(doc))

additional_salary = frappe.new_doc("Additional Salary")
additional_salary = xhiveframework.new_doc("Additional Salary")
additional_salary.employee = doc.employee
additional_salary.currency = doc.currency
additional_salary.amount = doc.paid_amount - doc.claimed_amount
@@ -244,7 +244,7 @@ def create_return_through_additional_salary(doc):
return additional_salary


@frappe.whitelist()
@xhiveframework.whitelist()
def make_return_entry(
employee,
company,
@@ -259,11 +259,11 @@ def make_return_entry(
company, account_type="Cash", mode_of_payment=mode_of_payment
)
if not bank_cash_account:
frappe.throw(_("Please set a Default Cash Account in Company defaults"))
xhiveframework.throw(_("Please set a Default Cash Account in Company defaults"))

advance_account_currency = frappe.db.get_value("Account", advance_account, "account_currency")
advance_account_currency = xhiveframework.db.get_value("Account", advance_account, "account_currency")

je = frappe.new_doc("Journal Entry")
je = xhiveframework.new_doc("Journal Entry")
je.posting_date = nowdate()
je.voucher_type = get_voucher_type(mode_of_payment)
je.company = company
@@ -288,7 +288,7 @@ def make_return_entry(
"party_type": "Employee",
"party": employee,
"is_advance": "Yes",
"cost_center": erpnext.get_default_cost_center(company),
"cost_center": xhiveerp.get_default_cost_center(company),
},
)

@@ -306,7 +306,7 @@ def make_return_entry(
"account_currency": bank_cash_account.account_currency,
"account_type": bank_cash_account.account_type,
"exchange_rate": flt(exchange_rate) if bank_cash_account.account_currency == currency else 1,
"cost_center": erpnext.get_default_cost_center(company),
"cost_center": xhiveerp.get_default_cost_center(company),
},
)

@@ -317,7 +317,7 @@ def get_voucher_type(mode_of_payment=None):
voucher_type = "Cash Entry"

if mode_of_payment:
mode_of_payment_type = frappe.get_cached_value("Mode of Payment", mode_of_payment, "type")
mode_of_payment_type = xhiveframework.get_cached_value("Mode of Payment", mode_of_payment, "type")
if mode_of_payment_type == "Bank":
voucher_type = "Bank Entry"



+ 11
- 11
hrms/hr/doctype/employee_advance/test_employee_advance.py Wyświetl plik

@@ -1,13 +1,13 @@
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2017, Xhive LLC
# See license.txt

import unittest

import frappe
from frappe.utils import flt, nowdate
import xhiveframework
from xhiveframework.utils import flt, nowdate

import erpnext
from erpnext.setup.doctype.employee.test_employee import make_employee
import xhiveerp
from xhiveerp.setup.doctype.employee.test_employee import make_employee

from hrms.hr.doctype.employee_advance.employee_advance import (
EmployeeAdvanceOverPayment,
@@ -26,7 +26,7 @@ from hrms.payroll.doctype.salary_structure.test_salary_structure import make_sal

class TestEmployeeAdvance(unittest.TestCase):
def setUp(self):
frappe.db.delete("Employee Advance")
xhiveframework.db.delete("Employee Advance")

def test_paid_amount_and_status(self):
employee_name = make_employee("_T@employe.advance")
@@ -135,7 +135,7 @@ class TestEmployeeAdvance(unittest.TestCase):
exchange_rate=advance.exchange_rate,
)

entry = frappe.get_doc(entry)
entry = xhiveframework.get_doc(entry)
entry.insert()
entry.submit()

@@ -202,11 +202,11 @@ class TestEmployeeAdvance(unittest.TestCase):
self.assertEqual(advance.status, "Paid")

def tearDown(self):
frappe.db.rollback()
xhiveframework.db.rollback()


def make_payment_entry(advance):
journal_entry = frappe.get_doc(make_bank_entry("Employee Advance", advance.name))
journal_entry = xhiveframework.get_doc(make_bank_entry("Employee Advance", advance.name))
journal_entry.cheque_no = "123123"
journal_entry.cheque_date = nowdate()
journal_entry.save()
@@ -215,11 +215,11 @@ def make_payment_entry(advance):


def make_employee_advance(employee_name, args=None):
doc = frappe.new_doc("Employee Advance")
doc = xhiveframework.new_doc("Employee Advance")
doc.employee = employee_name
doc.company = "_Test Company"
doc.purpose = "For site visit"
doc.currency = erpnext.get_company_currency("_Test company")
doc.currency = xhiveerp.get_company_currency("_Test company")
doc.exchange_rate = 1
doc.advance_amount = 1000
doc.posting_date = nowdate()


+ 10
- 10
hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.js Wyświetl plik

@@ -1,4 +1,4 @@
frappe.ui.form.on("Employee Attendance Tool", {
xhiveframework.ui.form.on("Employee Attendance Tool", {
refresh(frm) {
frm.trigger("reset_attendance_fields")
frm.trigger("load_employees");
@@ -6,7 +6,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
},

onload(frm) {
frm.set_value("date", frappe.datetime.get_today());
frm.set_value("date", xhiveframework.datetime.get_today());
},

date(frm) {
@@ -40,7 +40,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
if (!frm.doc.date)
return;

frappe.call({
xhiveframework.call({
method: "hrms.hr.doctype.employee_attendance_tool.employee_attendance_tool.get_employees",
args: {
date: frm.doc.date,
@@ -74,7 +74,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
$wrapper.empty();
const employee_wrapper = $(`<div class="employee_wrapper">`).appendTo($wrapper);

frm.employees_multicheck = frappe.ui.form.make_control({
frm.employees_multicheck = xhiveframework.ui.form.make_control({
parent: employee_wrapper,
df: {
fieldname: "employees_multicheck",
@@ -122,7 +122,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
noDataMessage: __("No Data"),
disableReorderColumn: true,
};
frm.marked_emp_datatable = new frappe.DataTable(
frm.marked_emp_datatable = new xhiveframework.DataTable(
summary_wrapper.get(0),
datatable_options,
);
@@ -172,7 +172,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
frm.disable_save();
frm.page.set_primary_action(__("Mark Attendance"), () => {
if (frm.employees.length === 0) {
frappe.msgprint({
xhiveframework.msgprint({
message: __("Attendance for all the employees under this criteria has been marked already."),
title: __("Attendance Marked"),
indicator: "green"
@@ -181,14 +181,14 @@ frappe.ui.form.on("Employee Attendance Tool", {
}

if (frm.employees_multicheck.get_checked_options().length === 0) {
frappe.throw({
xhiveframework.throw({
message: __("Please select the employees you want to mark attendance for."),
title: __("Mandatory")
});
}

if (!frm.doc.status) {
frappe.throw({
xhiveframework.throw({
message: __("Please select the attendance status."),
title: __("Mandatory")
});
@@ -201,7 +201,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
mark_attendance(frm) {
const marked_employees = frm.employees_multicheck.get_checked_options();

frappe.call({
xhiveframework.call({
method: "hrms.hr.doctype.employee_attendance_tool.employee_attendance_tool.mark_employee_attendance",
args: {
employee_list: marked_employees,
@@ -215,7 +215,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
freeze_message: __("Marking Attendance")
}).then((r) => {
if (!r.exc) {
frappe.show_alert({ message: __("Attendance marked successfully"), indicator: "green" });
xhiveframework.show_alert({ message: __("Attendance marked successfully"), indicator: "green" });
frm.refresh();
}
});


+ 9
- 9
hrms/hr/doctype/employee_attendance_tool/employee_attendance_tool.py Wyświetl plik

@@ -1,20 +1,20 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2015, Xhive LLC
# For license information, please see license.txt


import datetime
import json

import frappe
from frappe.model.document import Document
from frappe.utils import getdate
import xhiveframework
from xhiveframework.model.document import Document
from xhiveframework.utils import getdate


class EmployeeAttendanceTool(Document):
pass


@frappe.whitelist()
@xhiveframework.whitelist()
def get_employees(
date: str | datetime.date, department: str = None, branch: str = None, company: str = None
) -> dict[str, list]:
@@ -24,10 +24,10 @@ def get_employees(
if value:
filters[field] = value

employee_list = frappe.get_list(
employee_list = xhiveframework.get_list(
"Employee", fields=["employee", "employee_name"], filters=filters, order_by="employee_name"
)
attendance_list = frappe.get_list(
attendance_list = xhiveframework.get_list(
"Attendance",
fields=["employee", "employee_name", "status"],
filters={
@@ -53,7 +53,7 @@ def _get_unmarked_attendance(employee_list: list[dict], attendance_list: list[di
return unmarked_attendance


@frappe.whitelist()
@xhiveframework.whitelist()
def mark_employee_attendance(
employee_list: list | str,
status: str,
@@ -72,7 +72,7 @@ def mark_employee_attendance(
if status == "On Leave" and leave_type:
leave_type = leave_type

attendance = frappe.get_doc(
attendance = xhiveframework.get_doc(
dict(
doctype="Attendance",
employee=employee,


+ 8
- 8
hrms/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2023, Xhive LLC
# See license.txt

import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import getdate
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase
from xhiveframework.utils import getdate

from erpnext.setup.doctype.employee.test_employee import make_employee
from xhiveerp.setup.doctype.employee.test_employee import make_employee

from hrms.hr.doctype.attendance.attendance import mark_attendance
from hrms.hr.doctype.employee_attendance_tool.employee_attendance_tool import (
@@ -15,9 +15,9 @@ from hrms.hr.doctype.employee_attendance_tool.employee_attendance_tool import (
from hrms.hr.doctype.shift_type.test_shift_type import setup_shift_type


class TestEmployeeAttendanceTool(FrappeTestCase):
class TestEmployeeAttendanceTool(XhiveframeworkTestCase):
def setUp(self):
frappe.db.delete("Attendance")
xhiveframework.db.delete("Attendance")

self.employee1 = make_employee("test_present@example.com", company="_Test Company")
self.employee2 = make_employee("test_absent@example.com", company="_Test Company")
@@ -56,7 +56,7 @@ class TestEmployeeAttendanceTool(FrappeTestCase):
late_entry=1,
)

attendance = frappe.db.get_value(
attendance = xhiveframework.db.get_value(
"Attendance",
{"employee": self.employee1, "attendance_date": date},
["status", "shift", "late_entry"],


+ 2
- 2
hrms/hr/doctype/employee_boarding_activity/employee_boarding_activity.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2018, Xhive LLC
# For license information, please see license.txt


from frappe.model.document import Document
from xhiveframework.model.document import Document


class EmployeeBoardingActivity(Document):


+ 2
- 2
hrms/hr/doctype/employee_checkin/employee_checkin.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2019, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Employee Checkin', {
xhiveframework.ui.form.on('Employee Checkin', {
// setup: (frm) => {

// }


+ 21
- 21
hrms/hr/doctype/employee_checkin/employee_checkin.py Wyświetl plik

@@ -1,11 +1,11 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2019, Xhive LLC
# For license information, please see license.txt


import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import cint, get_datetime, get_link_to_form
import xhiveframework
from xhiveframework import _
from xhiveframework.model.document import Document
from xhiveframework.utils import cint, get_datetime, get_link_to_form

from hrms.hr.doctype.attendance.attendance import (
get_duplicate_attendance_record,
@@ -24,12 +24,12 @@ class EmployeeCheckin(Document):
self.fetch_shift()

def validate_duplicate_log(self):
doc = frappe.db.exists(
doc = xhiveframework.db.exists(
"Employee Checkin", {"employee": self.employee, "time": self.time, "name": ["!=", self.name]}
)
if doc:
doc_link = frappe.get_desk_link("Employee Checkin", doc)
frappe.throw(
doc_link = xhiveframework.get_desk_link("Employee Checkin", doc)
xhiveframework.throw(
_("This employee already has a log with the same timestamp.{0}").format("<Br>" + doc_link)
)

@@ -44,7 +44,7 @@ class EmployeeCheckin(Document):
and not self.log_type
and not self.skip_auto_attendance
):
frappe.throw(
xhiveframework.throw(
_("Log Type is required for check-ins falling in the shift: {0}.").format(
shift_actual_timings.shift_type.name
)
@@ -59,7 +59,7 @@ class EmployeeCheckin(Document):
self.shift = None


@frappe.whitelist()
@xhiveframework.whitelist()
def add_log_based_on_employee_field(
employee_field_value,
timestamp,
@@ -79,9 +79,9 @@ def add_log_based_on_employee_field(
"""

if not employee_field_value or not timestamp:
frappe.throw(_("'employee_field_value' and 'timestamp' are required."))
xhiveframework.throw(_("'employee_field_value' and 'timestamp' are required."))

employee = frappe.db.get_values(
employee = xhiveframework.db.get_values(
"Employee",
{employee_fieldname: employee_field_value},
["name", "employee_name", employee_fieldname],
@@ -90,13 +90,13 @@ def add_log_based_on_employee_field(
if employee:
employee = employee[0]
else:
frappe.throw(
xhiveframework.throw(
_("No Employee found for the given employee field value. '{}': {}").format(
employee_fieldname, employee_field_value
)
)

doc = frappe.new_doc("Employee Checkin")
doc = xhiveframework.new_doc("Employee Checkin")
doc.employee = employee.name
doc.employee_name = employee.employee_name
doc.time = timestamp
@@ -136,7 +136,7 @@ def mark_attendance_and_link_log(
return None

elif attendance_status in ("Present", "Absent", "Half Day"):
employee_doc = frappe.get_doc("Employee", employee)
employee_doc = xhiveframework.get_doc("Employee", employee)
duplicate = get_duplicate_attendance_record(employee, attendance_date, shift)
overlapping = get_overlapping_shift_attendance(employee, attendance_date, shift)

@@ -154,7 +154,7 @@ def mark_attendance_and_link_log(
"in_time": in_time,
"out_time": out_time,
}
attendance = frappe.get_doc(doc_dict).insert()
attendance = xhiveframework.get_doc(doc_dict).insert()
attendance.submit()

if attendance_status == "Absent":
@@ -162,7 +162,7 @@ def mark_attendance_and_link_log(
text=_("Employee was marked Absent for not meeting the working hours threshold.")
)

frappe.db.sql(
xhiveframework.db.sql(
"""update `tabEmployee Checkin`
set attendance = %s
where name in %s""",
@@ -175,7 +175,7 @@ def mark_attendance_and_link_log(
return None

else:
frappe.throw(_("{} is an invalid Attendance Status.").format(attendance_status))
xhiveframework.throw(_("{} is an invalid Attendance Status.").format(attendance_status))


def calculate_working_hours(logs, check_in_out_type, working_hours_calc_type):
@@ -258,7 +258,7 @@ def add_comment_in_checkins(log_names, duplicate, overlapping):
)

for name in log_names:
frappe.get_doc(
xhiveframework.get_doc(
{
"doctype": "Comment",
"comment_type": "Comment",
@@ -270,9 +270,9 @@ def add_comment_in_checkins(log_names, duplicate, overlapping):


def skip_attendance_in_checkins(log_names):
EmployeeCheckin = frappe.qb.DocType("Employee Checkin")
EmployeeCheckin = xhiveframework.qb.DocType("Employee Checkin")
(
frappe.qb.update(EmployeeCheckin)
xhiveframework.qb.update(EmployeeCheckin)
.set("skip_auto_attendance", 1)
.where(EmployeeCheckin.name.isin(log_names))
).run()

+ 21
- 21
hrms/hr/doctype/employee_checkin/test_employee_checkin.py Wyświetl plik

@@ -1,12 +1,12 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2019, Xhive LLC
# See license.txt

import unittest
from datetime import datetime, timedelta

import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import (
import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase
from xhiveframework.utils import (
add_days,
get_time,
get_year_ending,
@@ -16,8 +16,8 @@ from frappe.utils import (
nowdate,
)

from erpnext.setup.doctype.employee.test_employee import make_employee
from erpnext.setup.doctype.holiday_list.test_holiday_list import set_holiday_list
from xhiveerp.setup.doctype.employee.test_employee import make_employee
from xhiveerp.setup.doctype.holiday_list.test_holiday_list import set_holiday_list

from hrms.hr.doctype.employee_checkin.employee_checkin import (
add_log_based_on_employee_field,
@@ -29,11 +29,11 @@ from hrms.hr.doctype.shift_type.test_shift_type import make_shift_assignment, se
from hrms.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list


class TestEmployeeCheckin(FrappeTestCase):
class TestEmployeeCheckin(XhiveframeworkTestCase):
def setUp(self):
frappe.db.delete("Shift Type")
frappe.db.delete("Shift Assignment")
frappe.db.delete("Employee Checkin")
xhiveframework.db.delete("Shift Type")
xhiveframework.db.delete("Shift Assignment")
xhiveframework.db.delete("Employee Checkin")

from_date = get_year_start(getdate())
to_date = get_year_ending(getdate())
@@ -41,7 +41,7 @@ class TestEmployeeCheckin(FrappeTestCase):

def test_add_log_based_on_employee_field(self):
employee = make_employee("test_add_log_based_on_employee_field@example.com")
employee = frappe.get_doc("Employee", employee)
employee = xhiveframework.get_doc("Employee", employee)
employee.attendance_device_id = "3344"
employee.save()

@@ -57,21 +57,21 @@ class TestEmployeeCheckin(FrappeTestCase):
logs = make_n_checkins(employee, 3)
mark_attendance_and_link_log(logs, "Skip", nowdate())
log_names = [log.name for log in logs]
logs_count = frappe.db.count(
logs_count = xhiveframework.db.count(
"Employee Checkin", {"name": ["in", log_names], "skip_auto_attendance": 1}
)
self.assertEqual(logs_count, 3)

logs = make_n_checkins(employee, 4, 2)
now_date = nowdate()
frappe.db.delete("Attendance", {"employee": employee})
xhiveframework.db.delete("Attendance", {"employee": employee})
attendance = mark_attendance_and_link_log(logs, "Present", now_date, 8.2)
log_names = [log.name for log in logs]
logs_count = frappe.db.count(
logs_count = xhiveframework.db.count(
"Employee Checkin", {"name": ["in", log_names], "attendance": attendance.name}
)
self.assertEqual(logs_count, 4)
attendance_count = frappe.db.count(
attendance_count = xhiveframework.db.count(
"Attendance",
{"status": "Present", "working_hours": 8.2, "employee": employee, "attendance_date": now_date},
)
@@ -81,11 +81,11 @@ class TestEmployeeCheckin(FrappeTestCase):
employee = make_employee("test_mark_attendance_and_link_log@example.com")
logs = make_n_checkins(employee, 3)

frappe.db.delete("Attendance", {"employee": employee})
xhiveframework.db.delete("Attendance", {"employee": employee})
attendance = mark_attendance_and_link_log(logs, "Present", nowdate(), 8.2)
attendance.cancel()

linked_logs = frappe.db.get_all("Employee Checkin", {"attendance": attendance.name})
linked_logs = xhiveframework.db.get_all("Employee Checkin", {"attendance": attendance.name})
self.assertEquals(len(linked_logs), 0)

def test_calculate_working_hours(self):
@@ -114,8 +114,8 @@ class TestEmployeeCheckin(FrappeTestCase):
{"time": now_datetime() - timedelta(minutes=150), "log_type": "IN"},
{"time": now_datetime() - timedelta(minutes=60), "log_type": "OUT"},
]
logs_type_1 = [frappe._dict(x) for x in logs_type_1]
logs_type_2 = [frappe._dict(x) for x in logs_type_2]
logs_type_1 = [xhiveframework._dict(x) for x in logs_type_1]
logs_type_2 = [xhiveframework._dict(x) for x in logs_type_2]

working_hours = calculate_working_hours(
logs_type_1, check_in_out_type[0], working_hours_calc_type[0]
@@ -219,7 +219,7 @@ class TestEmployeeCheckin(FrappeTestCase):
)

date = getdate()
frappe.db.set_value("Employee", employee, "default_shift", default_shift.name)
xhiveframework.db.set_value("Employee", employee, "default_shift", default_shift.name)

timestamp = datetime.combine(date, get_time("14:45:00"))
log = make_checkin(employee, timestamp)
@@ -305,7 +305,7 @@ def make_n_checkins(employee, n, hours_to_reverse=1):


def make_checkin(employee, time=now_datetime()):
log = frappe.get_doc(
log = xhiveframework.get_doc(
{
"doctype": "Employee Checkin",
"employee": employee,


+ 2
- 2
hrms/hr/doctype/employee_feedback_criteria/employee_feedback_criteria.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2023, Xhive LLC
// For license information, please see license.txt

// frappe.ui.form.on("Employee Feedback Criteria", {
// xhiveframework.ui.form.on("Employee Feedback Criteria", {
// refresh(frm) {

// },


+ 3
- 3
hrms/hr/doctype/employee_feedback_criteria/employee_feedback_criteria.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2023, Xhive LLC
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class EmployeeFeedbackCriteria(Document):


+ 4
- 4
hrms/hr/doctype/employee_feedback_criteria/test_employee_feedback_criteria.py Wyświetl plik

@@ -1,9 +1,9 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2023, Xhive LLC
# See license.txt

# import frappe
from frappe.tests.utils import FrappeTestCase
# import xhiveframework
from xhiveframework.tests.utils import XhiveframeworkTestCase


class TestEmployeeFeedbackCriteria(FrappeTestCase):
class TestEmployeeFeedbackCriteria(XhiveframeworkTestCase):
pass

+ 3
- 3
hrms/hr/doctype/employee_feedback_rating/employee_feedback_rating.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2022, Xhive LLC
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document
# import xhiveframework
from xhiveframework.model.document import Document


class EmployeeFeedbackRating(Document):


+ 2
- 2
hrms/hr/doctype/employee_grade/employee_grade.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2018, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Employee Grade', {
xhiveframework.ui.form.on('Employee Grade', {
refresh: function (frm) {

},


+ 2
- 2
hrms/hr/doctype/employee_grade/employee_grade.py Wyświetl plik

@@ -1,8 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2018, Xhive LLC
# For license information, please see license.txt


from frappe.model.document import Document
from xhiveframework.model.document import Document


class EmployeeGrade(Document):


+ 1
- 1
hrms/hr/doctype/employee_grade/test_employee_grade.py Wyświetl plik

@@ -1,4 +1,4 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2018, Xhive LLC
# See license.txt

import unittest


+ 2
- 2
hrms/hr/doctype/employee_grievance/employee_grievance.js Wyświetl plik

@@ -1,7 +1,7 @@
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// Copyright (c) 2021, Xhive LLC
// For license information, please see license.txt

frappe.ui.form.on('Employee Grievance', {
xhiveframework.ui.form.on('Employee Grievance', {
setup: function(frm) {
frm.set_query('grievance_against_party', function() {
return {


+ 5
- 5
hrms/hr/doctype/employee_grievance/employee_grievance.py Wyświetl plik

@@ -1,15 +1,15 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2021, Xhive LLC
# For license information, please see license.txt

import frappe
from frappe import _, bold
from frappe.model.document import Document
import xhiveframework
from xhiveframework import _, bold
from xhiveframework.model.document import Document


class EmployeeGrievance(Document):
def on_submit(self):
if self.status not in ["Invalid", "Resolved"]:
frappe.throw(
xhiveframework.throw(
_("Only Employee Grievance with status {0} or {1} can be submitted").format(
bold("Invalid"), bold("Resolved")
)


+ 1
- 1
hrms/hr/doctype/employee_grievance/employee_grievance_list.js Wyświetl plik

@@ -1,4 +1,4 @@
frappe.listview_settings["Employee Grievance"] = {
xhiveframework.listview_settings["Employee Grievance"] = {
has_indicator_for_draft: 1,
get_indicator: function(doc) {
var colors = {


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików

Ładowanie…
Anuluj
Zapisz