Skip to content

Commit

Permalink
Merge branch 'master-14' into fix-conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
mymi14s authored Jan 11, 2024
2 parents 3de86ea + 0f7e11e commit 2b205af
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 44 deletions.
8 changes: 6 additions & 2 deletions one_fm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@
from hrms.hr.doctype.shift_assignment.shift_assignment import ShiftAssignment
from one_fm.overrides.shift_assignment import ShiftAssignmentOverride
from hrms.hr.doctype.leave_policy_assignment.leave_policy_assignment import LeavePolicyAssignment
from hrms.hr.doctype.goal.goal import get_children
from erpnext.controllers.stock_controller import StockController
from one_fm.overrides.stock_controller import make_batches_with_supplier_batch_id
from frappe.automation.doctype.assignment_rule.assignment_rule import AssignmentRule
from one_fm.overrides.assignment_rule import do_assignment
from one_fm.overrides.goal import get_childrens


__version__ = '14.6.2'

__version__ = '14.6.3'

StockController.make_batches = make_batches_with_supplier_batch_id
Interview.validate_overlap = validate_interview_overlap
Expand Down Expand Up @@ -87,5 +91,5 @@
frappe.utils.nestedset.validate_loop = custom_validate_nestedset_loop
InterviewFeedback.validate_interviewer = custom_validate_interviewer
ShiftAssignment = ShiftAssignmentOverride

get_children = get_childrens
AssignmentRule.do_assignment = do_assignment
4 changes: 2 additions & 2 deletions one_fm/one_fm/doctype/google_sheet_data_export/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ def update_google_sheet_daily():

for e in list_of_export:
doc = frappe.get_doc("Google Sheet Data Export",e.name)
time.sleep(120)
time.sleep(20)

frappe.enqueue(export_data,
doctype= doc.reference_doctype,
Expand All @@ -573,7 +573,7 @@ def update_google_sheet_daily():
sheet_name= doc.sheet_name,
owner= doc.owner,
client_id= doc.client_id,
is_async=True, queue="long")
is_async=True, queue="long", timeout=6000)

@frappe.whitelist()
def get_client_id():
Expand Down
7 changes: 6 additions & 1 deletion one_fm/one_fm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,12 @@ def manage_attendance_on_holiday(doc, method):
if not is_site_allowance_exist_for_this_employee(doc.employee, doc.attendance_date):
create_additional_salary_from_attendance(doc, salary_component, remark)
if doc.status == "Present":
if not frappe.db.exists("Compensatory Leave Request",{'leave_type':leave_type,'employee':doc.employee,'work_from_date':doc.attendance_date,'work_end_date':doc.attendance_date,'docstatus':1}):
leave_request_exists = frappe.db.sql(f"""SELECT c.name from `tabCompensatory Leave Request` c
WHERE c.leave_type='{leave_type}'
AND c.employee='{doc.employee}'
AND {doc.attendance_date} BETWEEN c.work_from_date AND c.work_end_date
AND c.docstatus=1 """, as_dict=1)
if not leave_request_exists:
create_compensatory_leave_request_from_attendance(doc, leave_type, remark)

# cancel additional salary and compensatory leave request on attendance cancel
Expand Down
84 changes: 84 additions & 0 deletions one_fm/overrides/goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,87 @@ def update_kra_in_child_goals(self, doc_before_save):
frappe.msgprint(_("KRA updated for the child goals that share the same KRA as the parent."), alert=True, indicator="green")


@frappe.whitelist()
def get_childrens(doctype: str, parent: str, is_root: bool = False, **filters) -> list[dict]:
Goal = frappe.qb.DocType(doctype)

query = (
frappe.qb.from_(Goal)
.select(
Goal.name.as_("value"),
Goal.goal_name.as_("title"),
Goal.is_group.as_("expandable"),
Goal.status,
Goal.employee,
Goal.employee_name,
Goal.appraisal_cycle,
Goal.progress,
Goal.kra,
Goal.parent_goal
)
.where(Goal.status != "Archived")
)

if filters.get("employee"):
query = query.where(Goal.employee == filters.get("employee"))

if filters.get("appraisal_cycle"):
query = query.where(Goal.appraisal_cycle == filters.get("appraisal_cycle"))

if filters.get("goal"):
query = query.where(Goal.parent_goal == filters.get("goal"))
elif parent and not is_root:
# via expand child
query = query.where(Goal.parent_goal == parent)
else:
ifnull = CustomFunction("IFNULL", ["value", "default"])
query = query.where(ifnull(Goal.parent_goal, "") == "")

if filters.get("date_range"):
date_range = frappe.parse_json(filters.get("date_range"))

query = query.where(
(Goal.start_date.between(date_range[0], date_range[1]))
& ((Goal.end_date.isnull()) | (Goal.end_date.between(date_range[0], date_range[1])))
)

goals = query.orderby(Goal.employee, Goal.kra).run(as_dict=True)
_update_goal_completion_status(goals)

goal_names = [g.value for g in goals]

if parent == filters.get("employee") :
additional_goals = add_employee_child_goals(Goal, goal_names, employee=filters.get("employee"))
goals = goals + additional_goals

return goals

def add_employee_child_goals(Goal, goal_names, employee):
query = (
frappe.qb.from_(Goal)
.select(
Goal.name.as_("value"),
Goal.goal_name.as_("title"),
Goal.is_group.as_("expandable"),
Goal.status,
Goal.employee,
Goal.employee_name,
Goal.appraisal_cycle,
Goal.progress,
Goal.kra,
Goal.parent_goal
)
.where(Goal.status != "Archived")
)
if employee:
query = query.where(Goal.employee == employee)
if goal_names:
query = query.where(Goal.parent_goal.notin(goal_names))
goals = []
additional_goals = query.orderby(Goal.employee, Goal.kra).run(as_dict=True)
for i in additional_goals:
if i.value not in goal_names:
parent_goal_employee = frappe.get_value("Goal", {'parent_goal':i.parent_goal}, ['employee'])
if parent_goal_employee != employee:
goals.append(i)
return goals
84 changes: 50 additions & 34 deletions one_fm/overrides/leave_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,14 @@ def is_app_user(emp):
pass


class LeaveApplicationOverride(LeaveApplication):
class LeaveApplicationOverride(LeaveApplication):
def onload(self):
leave_attendances = frappe.db.get_all("Attendance", {"leave_application": self.name}, "name")
attendance_not_created = False
if self.total_leave_days > len(leave_attendances):
attendance_not_created = True
self.set_onload("attendance_not_created", attendance_not_created)

def validate(self):
self.validate_applicable_after()

Expand All @@ -84,7 +91,6 @@ def close_todo(self):
def on_submit(self):
self.close_todo()
self.close_shifts()
self.update_attendance()
return super().on_submit()
self.db_set('status', 'Approved')

Expand Down Expand Up @@ -165,37 +171,14 @@ def validate(self):
self.validate_optional_leave()
self.validate_applicable_after()

@frappe.whitelist()
def update_attendance(self):
if self.status != "Approved":
return

holiday_dates = []
if self.leave_type == 'Annual Leave' :
holidays = get_holidays_for_employee(employee=self.employee, start_date=self.from_date, end_date=self.to_date, only_non_weekly=True)
holiday_dates = [cstr(h.holiday_date) for h in holidays]

for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
date = dt.strftime("%Y-%m-%d")
attendance_name = frappe.db.exists(
"Attendance", dict(employee=self.employee, attendance_date=date, docstatus=("!=", 2))
)

# don't mark attendance for holidays
# if leave type does not include holidays within leaves as leaves
if date in holiday_dates:
if attendance_name:
# cancel and delete existing attendance for holidays
attendance = frappe.get_doc("Attendance", attendance_name)
attendance.flags.ignore_permissions = True
if attendance.docstatus == 1:
print('True')
attendance.db_set('status','Holiday')
frappe.db.commit()
else:
self.create_or_update_attendance(attendance_name, date, 'Holiday')
else:
self.create_or_update_attendance(attendance_name, date, 'On Leave')

if self.total_leave_days > 20:
frappe.enqueue(update_attendance_recods, self=self, is_async=True)
else:
update_attendance_recods(self)

def create_or_update_attendance(self, attendance_name, date, status):
if attendance_name:
Expand Down Expand Up @@ -396,7 +379,7 @@ def validate_attendance_check(self):
except:
frappe.log_error(title = "Error Updating Attendance Check",message=frappe.get_traceback())
frappe.throw("An Error Occured while updating Attendance Checks. Please review the error logs")

def on_update(self):
if self.status=='Rejected':
self.notify_employee()
Expand Down Expand Up @@ -430,20 +413,53 @@ def on_update(self):
frappe.db.set_value("Employee", self.employee, "status", "Vacation")
self.validate_attendance_check()
self.clear_employee_schedules()


def clear_employee_schedules(self):
last_doc = self.get_doc_before_save()
if last_doc and last_doc.get('workflow_state') != self.workflow_state:
if self.workflow_state == "Approved":
frappe.db.sql(
'''
DELETE FROM `tabEmployee Schedule` WHERE
DELETE FROM `tabEmployee Schedule` WHERE
employee = %s AND
date BETWEEN %s AND %s;
''', (self.employee, self.from_date, self.to_date)
)


def update_attendance_recods(self):
if self.status != "Approved":
return

holiday_dates = []
if self.leave_type == 'Annual Leave' :
holidays = get_holidays_for_employee(employee=self.employee, start_date=self.from_date, end_date=self.to_date, only_non_weekly=True)
holiday_dates = [cstr(h.holiday_date) for h in holidays]

for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
date = dt.strftime("%Y-%m-%d")
attendance_name = frappe.db.exists(
"Attendance", dict(employee=self.employee, attendance_date=date, docstatus=("!=", 2))
)

# don't mark attendance for holidays
# if leave type does not include holidays within leaves as leaves
if date in holiday_dates:
if attendance_name:
# cancel and delete existing attendance for holidays
attendance = frappe.get_doc("Attendance", attendance_name)
attendance.flags.ignore_permissions = True
if attendance.docstatus == 1:
attendance.db_set('status','Holiday')
frappe.db.commit()
else:
self.create_or_update_attendance(attendance_name, date, 'Holiday')
else:
self.create_or_update_attendance(attendance_name, date, 'On Leave')

frappe.msgprint(_("Attendance are created for the leave Appication {0}!".format(self.name)), alert=True)

@frappe.whitelist()
def get_leave_details(employee, date):
allocation_records = get_leave_allocation_records(employee, date)
Expand Down
23 changes: 18 additions & 5 deletions one_fm/public/js/doctype_js/leave_application.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,28 @@ frappe.ui.form.on("Leave Application", {
// $('.btn .btn-primary .btn-sm').show();
}
}
if (frm.doc.status == 'Approved' && frm.doc.__onload && frm.doc.__onload.attendance_not_created){
frm.add_custom_button(__('Update Attendance'),
function () {
frappe.call({
doc: frm.doc,
method: 'update_attendance',
callback: function(r) {
frm.reload_doc();
}
});
}
);
}
},
onload: function(frm) {
$.each(frm.fields_dict, function(fieldname, field) {
field.df.onchange = frm =>{
if (cur_frm.doc.employee && cur_frm.doc.leave_type == "Sick Leave"){
frappe.db.get_value("Employee", cur_frm.doc.employee, "is_in_kuwait").then(res=>{
frappe.db.get_value("Employee", cur_frm.doc.employee, "is_in_kuwait").then(res=>{
res.message.is_in_kuwait ? cur_frm.set_value("is_proof_document_required", 1) : cur_frm.set_value("is_proof_document_required", 0)
cur_frm.refresh_field("is_proof_document_required")

})
}
};
Expand All @@ -48,13 +61,13 @@ frappe.ui.form.on("Leave Application", {
})


var prefillForm = frm => {
var prefillForm = frm => {
const url = new URL(window.location.href);

const params = new URLSearchParams(url.search);

const doc_id = params.get('doc_id');
const doctype = params.get('doctype');
const doctype = params.get('doctype');

if (doctype == "Attendance Check"){
frappe.call({
Expand All @@ -69,7 +82,7 @@ var prefillForm = frm => {
callback: function(r) {
if (r.message) {
cur_frm.set_value("employee", r.message.employee)

}
}
});
Expand Down

0 comments on commit 2b205af

Please sign in to comment.