Skip to content

Commit

Permalink
feat: Tracking Multi-round interview (#25482) (#27724)
Browse files Browse the repository at this point in the history
* feat: Tracking Multi-round interview

* fix: releted to scheduler event and formating

* fix: job applicant UI/UX and conflicts

* test: Interview Round

* fix(test): Employee referral, Employee Onboarding, Job Offer

* fix: sider

* feat: set default value in Hr settings

* feat: added validation for designation

* test: Interview

* test: Added validatiolns for skill

* test: Interview feedback

* fix: sider

* fix: remove unnecessary validations and form label cleanups

* chore: clean-up Interview Round and Interview Type doctype

* fix: remove redundant Rating Value, only keep Rating

* fix: update interview details on feedback submission

- make interview feedback submission dialog minimizable

* fix: show submit feedback button only if feedback doesn't exist

* refactor: Interview and Feedback statuses and workflow

* fix(HR Settings): clean up interview settings

* refactor: Interview

* refactor: Interview Feedback, remove unnecessary validations

* chore: update notification messages

* chore: remove unnecessary formatting changes in attendance list and leave application

* refactor: Job Applicant to Interview mapping

* chore: sorted imports

* chore: sorted imports

* fix: sider issues

* fix: linter issues

* fix: sider issues

* fix: tests

* fix: sorted imports

* fix: tests, sider

* fix: therapy plan test

* fix: sider issues

* feat: Include From Time and To Time fields in Interview for cleaner data

* feat: Interview Calendar

* fix: allow renaming masters

* fix: add more fields to list view and standard filter

* fix: validate overlapping interviews

* fix: update tests

* fix: linter issues

* refactor: replace reminder messages with Email Templates

* fix: sider issues

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
(cherry picked from commit 57e66f9)

Co-authored-by: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
  • Loading branch information
mergify[bot] and Anurag810 authored Oct 1, 2021
1 parent a04f9c9 commit b9942ad
Show file tree
Hide file tree
Showing 60 changed files with 2,385 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class TestPatientMedicalRecord(unittest.TestCase):
def setUp(self):
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
frappe.db.sql('delete from `tabPatient Appointment`')
make_pos_profile()

def test_medical_record(self):
Expand Down
5 changes: 4 additions & 1 deletion erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import unittest

import frappe
from frappe.utils import flt, getdate, nowdate
from frappe.utils import add_days, flt, getdate, nowdate

from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import (
create_appointment,
Expand All @@ -33,17 +33,20 @@ def test_status(self):
self.assertEqual(plan.status, 'Not Started')

session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
session.start_date = getdate()
frappe.get_doc(session).submit()
self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')

session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
session.start_date = add_days(getdate(), 1)
frappe.get_doc(session).submit()
self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')

patient, practitioner = create_healthcare_docs()
appointment = create_appointment(patient, practitioner, nowdate())

session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company', appointment.name)
session.start_date = add_days(getdate(), 2)
session = frappe.get_doc(session)
session.submit()
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
Expand Down
4 changes: 1 addition & 3 deletions erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import frappe
from frappe.model.document import Document
from frappe.utils import flt, today
from frappe.utils import flt


class TherapyPlan(Document):
Expand Down Expand Up @@ -63,8 +63,6 @@ def make_therapy_session(therapy_plan, patient, therapy_type, company, appointme
therapy_session.exercises = therapy_type.exercises
therapy_session.appointment = appointment

if frappe.flags.in_test:
therapy_session.start_date = today()
return therapy_session.as_dict()


Expand Down
2 changes: 2 additions & 0 deletions erpnext/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@
"all": [
"erpnext.projects.doctype.project.project.project_status_update_reminder",
"erpnext.healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder",
"erpnext.hr.doctype.interview.interview.send_interview_reminder",
"erpnext.crm.doctype.social_media_post.social_media_post.process_scheduled_social_media_posts"
],
"hourly": [
Expand Down Expand Up @@ -388,6 +389,7 @@
"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status",
"erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email",
"erpnext.non_profit.doctype.membership.membership.set_expired_status"
"erpnext.hr.doctype.interview.interview.send_daily_feedback_reminder"
],
"daily_long": [
"erpnext.setup.doctype.email_digest.email_digest.send",
Expand Down
138 changes: 73 additions & 65 deletions erpnext/hr/doctype/attendance/attendance_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,83 +9,86 @@ frappe.listview_settings['Attendance'] = {
return [__(doc.status), "orange", "status,=," + doc.status];
}
},

onload: function(list_view) {
let me = this;
const months = moment.months()
list_view.page.add_inner_button( __("Mark Attendance"), function() {
const months = moment.months();
list_view.page.add_inner_button(__("Mark Attendance"), function() {
let dialog = new frappe.ui.Dialog({
title: __("Mark Attendance"),
fields: [
{
fieldname: 'employee',
label: __('For Employee'),
fieldtype: 'Link',
options: 'Employee',
get_query: () => {
return {query: "erpnext.controllers.queries.employee_query"}
},
reqd: 1,
onchange: function() {
dialog.set_df_property("unmarked_days", "hidden", 1);
dialog.set_df_property("status", "hidden", 1);
dialog.set_df_property("month", "value", '');
fields: [{
fieldname: 'employee',
label: __('For Employee'),
fieldtype: 'Link',
options: 'Employee',
get_query: () => {
return {query: "erpnext.controllers.queries.employee_query"};
},
reqd: 1,
onchange: function() {
dialog.set_df_property("unmarked_days", "hidden", 1);
dialog.set_df_property("status", "hidden", 1);
dialog.set_df_property("month", "value", '');
dialog.set_df_property("unmarked_days", "options", []);
dialog.no_unmarked_days_left = false;
}
},
{
label: __("For Month"),
fieldtype: "Select",
fieldname: "month",
options: months,
reqd: 1,
onchange: function() {
if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
dialog.set_df_property("status", "hidden", 0);
dialog.set_df_property("unmarked_days", "options", []);
dialog.no_unmarked_days_left = false;
me.get_multi_select_options(dialog.fields_dict.employee.value, dialog.fields_dict.month.value).then(options => {
if (options.length > 0) {
dialog.set_df_property("unmarked_days", "hidden", 0);
dialog.set_df_property("unmarked_days", "options", options);
} else {
dialog.no_unmarked_days_left = true;
}
});
}
},
{
label: __("For Month"),
fieldtype: "Select",
fieldname: "month",
options: months,
reqd: 1,
onchange: function() {
if(dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
dialog.set_df_property("status", "hidden", 0);
dialog.set_df_property("unmarked_days", "options", []);
dialog.no_unmarked_days_left = false;
me.get_multi_select_options(dialog.fields_dict.employee.value, dialog.fields_dict.month.value).then(options =>{
if (options.length > 0) {
dialog.set_df_property("unmarked_days", "hidden", 0);
dialog.set_df_property("unmarked_days", "options", options);
} else {
dialog.no_unmarked_days_left = true;
}
});
}
}
},
{
label: __("Status"),
fieldtype: "Select",
fieldname: "status",
options: ["Present", "Absent", "Half Day", "Work From Home"],
hidden:1,
reqd: 1,
}
},
{
label: __("Status"),
fieldtype: "Select",
fieldname: "status",
options: ["Present", "Absent", "Half Day", "Work From Home"],
hidden: 1,
reqd: 1,

},
{
label: __("Unmarked Attendance for days"),
fieldname: "unmarked_days",
fieldtype: "MultiCheck",
options: [],
columns: 2,
hidden: 1
},
],
primary_action(data) {
},
{
label: __("Unmarked Attendance for days"),
fieldname: "unmarked_days",
fieldtype: "MultiCheck",
options: [],
columns: 2,
hidden: 1
}],
primary_action(data) {
if (cur_dialog.no_unmarked_days_left) {
frappe.msgprint(__("Attendance for the month of {0} , has already been marked for the Employee {1}",[dialog.fields_dict.month.value, dialog.fields_dict.employee.value]));
frappe.msgprint(__("Attendance for the month of {0} , has already been marked for the Employee {1}",
[dialog.fields_dict.month.value, dialog.fields_dict.employee.value]));
} else {
frappe.confirm(__('Mark attendance as {0} for {1} on selected dates?', [data.status,data.month]), () => {
frappe.confirm(__('Mark attendance as {0} for {1} on selected dates?', [data.status, data.month]), () => {
frappe.call({
method: "erpnext.hr.doctype.attendance.attendance.mark_bulk_attendance",
args: {
data: data
},
callback: function(r) {
callback: function (r) {
if (r.message === 1) {
frappe.show_alert({message: __("Attendance Marked"), indicator: 'blue'});
frappe.show_alert({
message: __("Attendance Marked"),
indicator: 'blue'
});
cur_dialog.hide();
}
}
Expand All @@ -101,21 +104,26 @@ frappe.listview_settings['Attendance'] = {
dialog.show();
});
},
get_multi_select_options: function(employee, month){

get_multi_select_options: function(employee, month) {
return new Promise(resolve => {
frappe.call({
method: 'erpnext.hr.doctype.attendance.attendance.get_unmarked_days',
async: false,
args:{
args: {
employee: employee,
month: month,
}
}).then(r => {
var options = [];
for(var d in r.message){
for (var d in r.message) {
var momentObj = moment(r.message[d], 'YYYY-MM-DD');
var date = momentObj.format('DD-MM-YYYY');
options.push({ "label":date, "value": r.message[d] , "checked": 1});
options.push({
"label": date,
"value": r.message[d],
"checked": 1
});
}
resolve(options);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def get_job_applicant():
applicant = frappe.new_doc('Job Applicant')
applicant.applicant_name = 'Test Researcher'
applicant.email_id = 'test@researcher.com'
applicant.designation = 'Researcher'
applicant.status = 'Open'
applicant.cover_letter = 'I am a great Researcher.'
applicant.insert()
Expand Down
2 changes: 2 additions & 0 deletions erpnext/hr/doctype/employee_referral/employee_referral.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ def create_job_applicant(source_name, target_doc=None):
status = "Open"

job_applicant = frappe.new_doc("Job Applicant")
job_applicant.source = "Employee Referral"
job_applicant.employee_referral = emp_ref.name
job_applicant.status = status
job_applicant.designation = emp_ref.for_designation
job_applicant.applicant_name = emp_ref.full_name
job_applicant.email_id = emp_ref.email
job_applicant.phone_number = emp_ref.contact_no
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@


class TestEmployeeReferral(unittest.TestCase):

def setUp(self):
frappe.db.sql("DELETE FROM `tabJob Applicant`")
frappe.db.sql("DELETE FROM `tabEmployee Referral`")

def test_workflow_and_status_sync(self):
emp_ref = create_employee_referral()

Expand Down Expand Up @@ -50,6 +55,10 @@ def test_workflow_and_status_sync(self):
add_sal = create_additional_salary(emp_ref)
self.assertTrue(add_sal.ref_docname, emp_ref.name)

def tearDown(self):
frappe.db.sql("DELETE FROM `tabJob Applicant`")
frappe.db.sql("DELETE FROM `tabEmployee Referral`")


def create_employee_referral():
emp_ref = frappe.new_doc("Employee Referral")
Expand Down
Empty file.
40 changes: 40 additions & 0 deletions erpnext/hr/doctype/expected_skill_set/expected_skill_set.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"actions": [],
"creation": "2021-04-12 13:05:06.741330",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"skill",
"description"
],
"fields": [
{
"fieldname": "skill",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Skill",
"options": "Skill",
"reqd": 1
},
{
"fetch_from": "skill.description",
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-04-12 14:26:33.062549",
"modified_by": "Administrator",
"module": "HR",
"name": "Expected Skill Set",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
12 changes: 12 additions & 0 deletions erpnext/hr/doctype/expected_skill_set/expected_skill_set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

from __future__ import unicode_literals

# import frappe
from frappe.model.document import Document


class ExpectedSkillSet(Document):
pass
Loading

0 comments on commit b9942ad

Please sign in to comment.