refactor: rewrite lwp queries using query builder
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 5a338bd..53c5df4 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -1201,25 +1201,33 @@
def get_approved_leaves_for_period(employee, leave_type, from_date, to_date):
- query = """
- select employee, leave_type, from_date, to_date, total_leave_days
- from `tabLeave Application`
- where employee=%(employee)s
- and docstatus=1
- and status='Approved'
- and (from_date between %(from_date)s and %(to_date)s
- or to_date between %(from_date)s and %(to_date)s
- or (from_date < %(from_date)s and to_date > %(to_date)s))
- """
- if leave_type:
- query += "and leave_type=%(leave_type)s"
-
- leave_applications = frappe.db.sql(
- query,
- {"from_date": from_date, "to_date": to_date, "employee": employee, "leave_type": leave_type},
- as_dict=1,
+ LeaveApplication = frappe.qb.DocType("Leave Application")
+ query = (
+ frappe.qb.from_(LeaveApplication)
+ .select(
+ LeaveApplication.employee,
+ LeaveApplication.leave_type,
+ LeaveApplication.from_date,
+ LeaveApplication.to_date,
+ LeaveApplication.total_leave_days,
+ )
+ .where(
+ (LeaveApplication.employee == employee)
+ & (LeaveApplication.docstatus == 1)
+ & (LeaveApplication.status == "Approved")
+ & (
+ (LeaveApplication.from_date.between(from_date, to_date))
+ | (LeaveApplication.to_date.between(from_date, to_date))
+ | ((LeaveApplication.from_date < from_date) & (LeaveApplication.to_date > to_date))
+ )
+ )
)
+ if leave_type:
+ query = query.where(LeaveApplication.leave_type == leave_type)
+
+ leave_applications = query.run(as_dict=True)
+
leave_days = 0
for leave_app in leave_applications:
if leave_app.from_date >= getdate(from_date) and leave_app.to_date <= getdate(to_date):
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
index 592e7dd..8dad7cc 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
@@ -207,27 +207,35 @@
def calculate_lwp(employee, start_date, holidays, working_days):
lwp = 0
holidays = "','".join(holidays)
+
for d in range(working_days):
dt = add_days(cstr(getdate(start_date)), d)
- leave = frappe.db.sql(
- """
- select t1.name, t1.half_day
- from `tabLeave Application` t1, `tabLeave Type` t2
- where t2.name = t1.leave_type
- and t2.is_lwp = 1
- and t1.docstatus = 1
- and t1.status = 'Approved'
- and t1.employee = %(employee)s
- and CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
- WHEN t2.include_holiday THEN %(dt)s between from_date and to_date
- END
- """.format(
- holidays
- ),
- {"employee": employee, "dt": dt},
+
+ LeaveApplication = frappe.qb.DocType("Leave Application")
+ LeaveType = frappe.qb.DocType("Leave Type")
+
+ query = (
+ frappe.qb.from_(LeaveApplication)
+ .inner_join(LeaveType)
+ .on((LeaveType.name == LeaveApplication.leave_type))
+ .select(LeaveApplication.name, LeaveApplication.half_day)
+ .where(
+ (LeaveType.is_lwp == 1)
+ & (LeaveApplication.docstatus == 1)
+ & (LeaveApplication.status == "Approved")
+ & (LeaveApplication.employee == employee)
+ & ((LeaveApplication.from_date <= dt) & (dt <= LeaveApplication.to_date))
+ )
)
- if leave:
- lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1)
+
+ # if it's a holiday only include if leave type has "include holiday" enabled
+ if dt in holidays:
+ query = query.where((LeaveType.include_holiday == "1"))
+ leaves = query.run()
+
+ if leaves:
+ lwp = cint(leaves[0][1]) and (lwp + 0.5) or (lwp + 1)
+
return lwp
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 378227f..6a35985 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -465,38 +465,14 @@
)
for d in range(working_days):
- dt = add_days(cstr(getdate(self.start_date)), d)
- leave = frappe.db.sql(
- """
- SELECT t1.name,
- CASE WHEN (t1.half_day_date = %(dt)s or t1.to_date = t1.from_date)
- THEN t1.half_day else 0 END,
- t2.is_ppl,
- t2.fraction_of_daily_salary_per_leave
- FROM `tabLeave Application` t1, `tabLeave Type` t2
- WHERE t2.name = t1.leave_type
- AND (t2.is_lwp = 1 or t2.is_ppl = 1)
- AND t1.docstatus = 1
- AND t1.status = 'Approved'
- AND t1.employee = %(employee)s
- AND ifnull(t1.salary_slip, '') = ''
- AND CASE
- WHEN t2.include_holiday != 1
- THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
- WHEN t2.include_holiday
- THEN %(dt)s between from_date and to_date
- END
- """.format(
- holidays
- ),
- {"employee": self.employee, "dt": dt},
- )
+ date = add_days(cstr(getdate(self.start_date)), d)
+ leave = get_lwp_or_ppl_for_date(date, self.employee, holidays)
if leave:
equivalent_lwp_count = 0
- is_half_day_leave = cint(leave[0][1])
- is_partially_paid_leave = cint(leave[0][2])
- fraction_of_daily_salary_per_leave = flt(leave[0][3])
+ is_half_day_leave = cint(leave[0].is_half_day)
+ is_partially_paid_leave = cint(leave[0].is_ppl)
+ fraction_of_daily_salary_per_leave = flt(leave[0].fraction_of_daily_salary_per_leave)
equivalent_lwp_count = (1 - daily_wages_fraction_for_half_day) if is_half_day_leave else 1
@@ -1743,3 +1719,46 @@
except Exception as e:
frappe.throw(_("Error in formula or condition: {0} in Income Tax Slab").format(e))
raise
+
+
+def get_lwp_or_ppl_for_date(date, employee, holidays):
+ LeaveApplication = frappe.qb.DocType("Leave Application")
+ LeaveType = frappe.qb.DocType("Leave Type")
+
+ is_half_day = (
+ frappe.qb.terms.Case()
+ .when(
+ (
+ (LeaveApplication.half_day_date == date)
+ | (LeaveApplication.from_date == LeaveApplication.to_date)
+ ),
+ LeaveApplication.half_day,
+ )
+ .else_(0)
+ ).as_("is_half_day")
+
+ query = (
+ frappe.qb.from_(LeaveApplication)
+ .inner_join(LeaveType)
+ .on((LeaveType.name == LeaveApplication.leave_type))
+ .select(
+ LeaveApplication.name,
+ LeaveType.is_ppl,
+ LeaveType.fraction_of_daily_salary_per_leave,
+ (is_half_day),
+ )
+ .where(
+ (((LeaveType.is_lwp == 1) | (LeaveType.is_ppl == 1)))
+ & (LeaveApplication.docstatus == 1)
+ & (LeaveApplication.status == "Approved")
+ & (LeaveApplication.employee == employee)
+ & ((LeaveApplication.salary_slip.isnull()) | (LeaveApplication.salary_slip == ""))
+ & ((LeaveApplication.from_date <= date) & (date <= LeaveApplication.to_date))
+ )
+ )
+
+ # if it's a holiday only include if leave type has "include holiday" enabled
+ if date in holidays:
+ query = query.where((LeaveType.include_holiday == "1"))
+
+ return query.run(as_dict=True)